diff --git a/packages/path_provider/path_provider_android/CHANGELOG.md b/packages/path_provider/path_provider_android/CHANGELOG.md index 816457564de8..2d53566fb0d3 100644 --- a/packages/path_provider/path_provider_android/CHANGELOG.md +++ b/packages/path_provider/path_provider_android/CHANGELOG.md @@ -1,6 +1,7 @@ -## NEXT +## 2.0.28 * Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. +* Adds support for getDownloadsDirectory in Android ## 2.0.27 diff --git a/packages/path_provider/path_provider_android/lib/path_provider_android.dart b/packages/path_provider/path_provider_android/lib/path_provider_android.dart index f5c74f540253..a87eace03dc6 100644 --- a/packages/path_provider/path_provider_android/lib/path_provider_android.dart +++ b/packages/path_provider/path_provider_android/lib/path_provider_android.dart @@ -81,7 +81,12 @@ class PathProviderAndroid extends PathProviderPlatform { } @override - Future getDownloadsPath() { - throw UnsupportedError('getDownloadsPath is not supported on Android'); + Future getDownloadsPath() async { + final List? paths = + await getExternalStoragePaths(type: StorageDirectory.downloads); + if (paths != null && paths.isNotEmpty) { + return paths.first; + } + return null; } } diff --git a/packages/path_provider/path_provider_android/pubspec.yaml b/packages/path_provider/path_provider_android/pubspec.yaml index ee8317394652..f0a82fac98bc 100644 --- a/packages/path_provider/path_provider_android/pubspec.yaml +++ b/packages/path_provider/path_provider_android/pubspec.yaml @@ -2,7 +2,7 @@ name: path_provider_android description: Android implementation of the path_provider plugin. repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 -version: 2.0.27 +version: 2.0.28 environment: sdk: ">=2.18.0 <4.0.0" @@ -23,9 +23,11 @@ dependencies: path_provider_platform_interface: ^2.0.1 dev_dependencies: + build_runner: ^2.3.2 flutter_test: sdk: flutter integration_test: sdk: flutter + mockito: 5.4.1 pigeon: ^9.2.4 test: ^1.16.0 diff --git a/packages/path_provider/path_provider_android/test/path_provider_android_test.dart b/packages/path_provider/path_provider_android/test/path_provider_android_test.dart index e3011474a2a3..0567a3b2fbf1 100644 --- a/packages/path_provider/path_provider_android/test/path_provider_android_test.dart +++ b/packages/path_provider/path_provider_android/test/path_provider_android_test.dart @@ -3,10 +3,13 @@ // found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; import 'package:path_provider_android/messages.g.dart' as messages; import 'package:path_provider_android/path_provider_android.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; import 'messages_test.g.dart'; +import 'path_provider_android_test.mocks.dart'; const String kTemporaryPath = 'temporaryPath'; const String kApplicationSupportPath = 'applicationSupportPath'; @@ -37,14 +40,17 @@ class _Api implements TestPathProviderApi { String? getTemporaryPath() => kTemporaryPath; } +@GenerateMocks([TestPathProviderApi]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('PathProviderAndroid', () { + late MockTestPathProviderApi mockApi; late PathProviderAndroid pathProvider; setUp(() async { pathProvider = PathProviderAndroid(); + mockApi = MockTestPathProviderApi(); TestPathProviderApi.setup(_Api()); }); @@ -89,13 +95,20 @@ void main() { }); } // end of for-loop - test('getDownloadsPath fails', () async { - try { - await pathProvider.getDownloadsPath(); - fail('should throw UnsupportedError'); - } catch (e) { - expect(e, isUnsupportedError); - } + test('getDownloadsPath succeeds', () async { + when(mockApi.getExternalStoragePaths(messages.StorageDirectory.downloads)) + .thenReturn([kDownloadsPath]); + final List path = + mockApi.getExternalStoragePaths(messages.StorageDirectory.downloads); + expect(path.first, kDownloadsPath); + }); + + test('getDownloadsPath null', () async { + when(mockApi.getExternalStoragePaths(messages.StorageDirectory.downloads)) + .thenReturn([null]); + final List path = + mockApi.getExternalStoragePaths(messages.StorageDirectory.downloads); + expect(path.first, null); }); }); } diff --git a/packages/path_provider/path_provider_android/test/path_provider_android_test.mocks.dart b/packages/path_provider/path_provider_android/test/path_provider_android_test.mocks.dart new file mode 100644 index 000000000000..2471dc166b65 --- /dev/null +++ b/packages/path_provider/path_provider_android/test/path_provider_android_test.mocks.dart @@ -0,0 +1,50 @@ +// Mocks generated by Mockito 5.4.1 from annotations +// in path_provider_android/test/path_provider_android_test.dart. +// Do not manually edit this file. + +// @dart=2.19 + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:mockito/mockito.dart' as _i1; +import 'package:path_provider_android/messages.g.dart' as _i3; + +import 'messages_test.g.dart' as _i2; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +/// A class which mocks [TestPathProviderApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTestPathProviderApi extends _i1.Mock + implements _i2.TestPathProviderApi { + MockTestPathProviderApi() { + _i1.throwOnMissingStub(this); + } + + @override + List getExternalCachePaths() => (super.noSuchMethod( + Invocation.method( + #getExternalCachePaths, + [], + ), + returnValue: [], + ) as List); + @override + List getExternalStoragePaths(_i3.StorageDirectory? directory) => + (super.noSuchMethod( + Invocation.method( + #getExternalStoragePaths, + [directory], + ), + returnValue: [], + ) as List); +}