[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);
+ }
+ });
+ });
+}