[path_provider] Switch Android to an internal method channel (#4617)
diff --git a/packages/path_provider/path_provider_android/CHANGELOG.md b/packages/path_provider/path_provider_android/CHANGELOG.md index 628bd44..f9d3543 100644 --- a/packages/path_provider/path_provider_android/CHANGELOG.md +++ b/packages/path_provider/path_provider_android/CHANGELOG.md
@@ -1,3 +1,7 @@ +## 2.0.10 + +* Switches to a package-internal implementation of the platform interface. + ## 2.0.9 * Updates Android compileSdkVersion to 31.
diff --git a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java index 3ff2416..278ff58 100644 --- a/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java +++ b/packages/path_provider/path_provider_android/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java
@@ -153,7 +153,7 @@ public PathProviderPlugin() {} private void setup(BinaryMessenger messenger, Context context) { - String channelName = "plugins.flutter.io/path_provider"; + String channelName = "plugins.flutter.io/path_provider_android"; // TODO(gaaclarke): Remove reflection guard when https://github.com/flutter/engine/pull/29147 // becomes available on the stable branch. try {
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 new file mode 100644 index 0000000..b0f3808 --- /dev/null +++ b/packages/path_provider/path_provider_android/lib/path_provider_android.dart
@@ -0,0 +1,67 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; + +/// The Android implementation of [PathProviderPlatform]. +class PathProviderAndroid extends PathProviderPlatform { + /// The method channel used to interact with the native platform. + @visibleForTesting + MethodChannel methodChannel = + const MethodChannel('plugins.flutter.io/path_provider_android'); + + /// Registers this class as the default instance of [PathProviderPlatform]. + static void registerWith() { + PathProviderPlatform.instance = PathProviderAndroid(); + } + + @override + Future<String?> getTemporaryPath() { + return methodChannel.invokeMethod<String>('getTemporaryDirectory'); + } + + @override + Future<String?> getApplicationSupportPath() { + return methodChannel.invokeMethod<String>('getApplicationSupportDirectory'); + } + + @override + Future<String?> getLibraryPath() { + throw UnsupportedError('getLibraryPath is not supported on Android'); + } + + @override + Future<String?> getApplicationDocumentsPath() { + return methodChannel + .invokeMethod<String>('getApplicationDocumentsDirectory'); + } + + @override + Future<String?> getExternalStoragePath() { + return methodChannel.invokeMethod<String>('getStorageDirectory'); + } + + @override + Future<List<String>?> getExternalCachePaths() { + return methodChannel + .invokeListMethod<String>('getExternalCacheDirectories'); + } + + @override + Future<List<String>?> getExternalStoragePaths({ + StorageDirectory? type, + }) async { + return methodChannel.invokeListMethod<String>( + 'getExternalStorageDirectories', + <String, dynamic>{'type': type?.index}, + ); + } + + @override + Future<String?> getDownloadsPath() { + throw UnsupportedError('getDownloadsPath is not supported on Android'); + } +}
diff --git a/packages/path_provider/path_provider_android/pubspec.yaml b/packages/path_provider/path_provider_android/pubspec.yaml index 09b26a5..5664ebf 100644 --- a/packages/path_provider/path_provider_android/pubspec.yaml +++ b/packages/path_provider/path_provider_android/pubspec.yaml
@@ -2,7 +2,7 @@ description: Android implementation of the path_provider plugin. repository: https://github.com/flutter/plugins/tree/master/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.9 +version: 2.0.10 environment: sdk: ">=2.14.0 <3.0.0" @@ -15,11 +15,12 @@ android: package: io.flutter.plugins.pathprovider pluginClass: PathProviderPlugin + dartPluginClass: PathProviderAndroid dependencies: flutter: sdk: flutter - path_provider_platform_interface: ^2.0.0 + path_provider_platform_interface: ^2.0.1 dev_dependencies: flutter_driver:
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 new file mode 100644 index 0000000..d2f9682 --- /dev/null +++ b/packages/path_provider/path_provider_android/test/path_provider_android_test.dart
@@ -0,0 +1,136 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider_android/path_provider_android.dart'; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + const String kTemporaryPath = 'temporaryPath'; + const String kApplicationSupportPath = 'applicationSupportPath'; + const String kLibraryPath = 'libraryPath'; + const String kApplicationDocumentsPath = 'applicationDocumentsPath'; + const String kExternalCachePaths = 'externalCachePaths'; + const String kExternalStoragePaths = 'externalStoragePaths'; + const String kDownloadsPath = 'downloadsPath'; + + group('PathProviderAndroid', () { + late PathProviderAndroid pathProvider; + final List<MethodCall> log = <MethodCall>[]; + + setUp(() async { + pathProvider = PathProviderAndroid(); + TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger + .setMockMethodCallHandler(pathProvider.methodChannel, + (MethodCall methodCall) async { + log.add(methodCall); + switch (methodCall.method) { + case 'getTemporaryDirectory': + return kTemporaryPath; + case 'getApplicationSupportDirectory': + return kApplicationSupportPath; + case 'getLibraryDirectory': + return kLibraryPath; + case 'getApplicationDocumentsDirectory': + return kApplicationDocumentsPath; + case 'getExternalStorageDirectories': + return <String>[kExternalStoragePaths]; + case 'getExternalCacheDirectories': + return <String>[kExternalCachePaths]; + case 'getDownloadsDirectory': + return kDownloadsPath; + default: + return null; + } + }); + }); + + tearDown(() { + log.clear(); + }); + + test('getTemporaryPath', () async { + final String? path = await pathProvider.getTemporaryPath(); + expect( + log, + <Matcher>[isMethodCall('getTemporaryDirectory', arguments: null)], + ); + expect(path, kTemporaryPath); + }); + + test('getApplicationSupportPath', () async { + final String? path = await pathProvider.getApplicationSupportPath(); + expect( + log, + <Matcher>[ + isMethodCall('getApplicationSupportDirectory', arguments: null) + ], + ); + expect(path, kApplicationSupportPath); + }); + + test('getLibraryPath fails', () async { + try { + await pathProvider.getLibraryPath(); + fail('should throw UnsupportedError'); + } catch (e) { + expect(e, isUnsupportedError); + } + }); + + test('getApplicationDocumentsPath', () async { + final String? path = await pathProvider.getApplicationDocumentsPath(); + expect( + log, + <Matcher>[ + isMethodCall('getApplicationDocumentsDirectory', arguments: null) + ], + ); + expect(path, kApplicationDocumentsPath); + }); + + test('getExternalCachePaths succeeds', () async { + final List<String>? result = await pathProvider.getExternalCachePaths(); + expect( + log, + <Matcher>[isMethodCall('getExternalCacheDirectories', arguments: null)], + ); + expect(result!.length, 1); + expect(result.first, kExternalCachePaths); + }); + + for (final StorageDirectory? type in <StorageDirectory?>[ + null, + ...StorageDirectory.values + ]) { + test('getExternalStoragePaths (type: $type) android succeeds', () async { + final List<String>? result = + await pathProvider.getExternalStoragePaths(type: type); + expect( + log, + <Matcher>[ + isMethodCall( + 'getExternalStorageDirectories', + arguments: <String, dynamic>{'type': type?.index}, + ) + ], + ); + + expect(result!.length, 1); + expect(result.first, kExternalStoragePaths); + }); + } // end of for-loop + + test('getDownloadsPath fails', () async { + try { + await pathProvider.getDownloadsPath(); + fail('should throw UnsupportedError'); + } catch (e) { + expect(e, isUnsupportedError); + } + }); + }); +}