-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[path_provider] Create platform interface #2553
Changes from all commits
807fbb4
4748861
c40e813
b049781
7543c0c
d4f1ba5
02b038a
678dd5d
d88af02
70cffb0
9085967
290e166
fcd271d
0d7dbbd
8d9219a
689ac16
7f7d351
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| ## 1.0.0 | ||
|
|
||
| * Initial release. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // Copyright 2020 The Chromium Authors. All rights reserved. | ||
| // | ||
| // Redistribution and use in source and binary forms, with or without | ||
| // modification, are permitted provided that the following conditions are | ||
| // met: | ||
| // | ||
| // * Redistributions of source code must retain the above copyright | ||
| // notice, this list of conditions and the following disclaimer. | ||
| // * Redistributions in binary form must reproduce the above | ||
| // copyright notice, this list of conditions and the following disclaimer | ||
| // in the documentation and/or other materials provided with the | ||
| // distribution. | ||
| // * Neither the name of Google Inc. nor the names of its | ||
| // contributors may be used to endorse or promote products derived from | ||
| // this software without specific prior written permission. | ||
| // | ||
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| # path_provider_platform_interface | ||
|
|
||
| A common platform interface for the [`path_provider`][1] plugin. | ||
|
|
||
| This interface allows platform-specific implementations of the `path_provider` | ||
| plugin, as well as the plugin itself, to ensure they are supporting the | ||
| same interface. | ||
|
|
||
| # Usage | ||
|
|
||
| To implement a new platform-specific implementation of `path_provider`, extend | ||
| [`PathProviderPlatform`][2] with an implementation that performs the | ||
| platform-specific behavior, and when you register your plugin, set the default | ||
| `PathProviderPlatform` by calling | ||
| `PathProviderPlatform.instance = MyPlatformPathProvider()`. | ||
|
|
||
| # Note on breaking changes | ||
|
|
||
| Strongly prefer non-breaking changes (such as adding a method to the interface) | ||
| over breaking changes for this package. | ||
|
|
||
| See https://flutter.dev/go/platform-interface-breaking-changes for a discussion | ||
| on why a less-clean interface is preferable to a breaking change. | ||
|
|
||
| [1]: ../ | ||
| [2]: lib/path_provider_platform_interface.dart |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| // Copyright 2020 The Chromium 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 'dart:async'; | ||
|
|
||
| import 'src/enums.dart'; | ||
| import 'src/method_channel_path_provider.dart'; | ||
|
|
||
| import 'package:plugin_platform_interface/plugin_platform_interface.dart'; | ||
|
|
||
| export 'src/enums.dart'; | ||
|
|
||
| /// The interface that implementations of path_provider must implement. | ||
| /// | ||
| /// Platform implementations should extend this class rather than implement it as `PathProvider` | ||
| /// does not consider newly added methods to be breaking changes. Extending this class | ||
| /// (using `extends`) ensures that the subclass will get the default implementation, while | ||
| /// platform implementations that `implements` this interface will be broken by newly added | ||
| /// [PathProviderPlatform] methods. | ||
| abstract class PathProviderPlatform extends PlatformInterface { | ||
| /// Constructs a PathProviderPlatform. | ||
| PathProviderPlatform() : super(token: _token); | ||
|
|
||
| static final Object _token = Object(); | ||
|
|
||
| static PathProviderPlatform _instance = MethodChannelPathProvider(); | ||
|
|
||
| /// The default instance of [PathProviderPlatform] to use. | ||
| /// | ||
| /// Defaults to [MethodChannelPathProvider]. | ||
| static PathProviderPlatform get instance => _instance; | ||
|
|
||
| /// Platform-specific plugins should set this with their own platform-specific | ||
| /// class that extends [PathProviderPlatform] when they register themselves. | ||
| static set instance(PathProviderPlatform instance) { | ||
| PlatformInterface.verifyToken(instance, _token); | ||
| _instance = instance; | ||
| } | ||
|
|
||
| /// Path to the temporary directory on the device that is not backed up and is | ||
| /// suitable for storing caches of downloaded files. | ||
| Future<String> getTemporaryPath() { | ||
| throw UnimplementedError('getTemporaryPath() has not been implemented.'); | ||
| } | ||
|
|
||
| /// Path to a directory where the application may place application support | ||
| /// files. | ||
| Future<String> getApplicationSupportPath() { | ||
| throw UnimplementedError( | ||
| 'getApplicationSupportPath() has not been implemented.'); | ||
| } | ||
|
|
||
| /// Path to the directory where application can store files that are persistent, | ||
| /// backed up, and not visible to the user, such as sqlite.db. | ||
| Future<String> getLibraryPath() { | ||
| throw UnimplementedError('getLibraryPath() has not been implemented.'); | ||
| } | ||
|
|
||
| /// Path to a directory where the application may place data that is | ||
| /// user-generated, or that cannot otherwise be recreated by your application. | ||
| Future<String> getApplicationDocumentsPath() { | ||
| throw UnimplementedError( | ||
| 'getApplicationDocumentsPath() has not been implemented.'); | ||
| } | ||
|
|
||
| /// Path to a directory where the application may access top level storage. | ||
| /// The current operating system should be determined before issuing this | ||
| /// function call, as this functionality is only available on Android. | ||
| Future<String> getExternalStoragePath() { | ||
| throw UnimplementedError( | ||
| 'getExternalStoragePath() has not been implemented.'); | ||
| } | ||
|
|
||
| /// Paths to directories where application specific external cache data can be | ||
| /// stored. These paths typically reside on external storage like separate | ||
| /// partitions or SD cards. Phones may have multiple storage directories | ||
| /// available. | ||
| Future<List<String>> getExternalCachePaths() { | ||
| throw UnimplementedError( | ||
| 'getExternalCachePaths() has not been implemented.'); | ||
| } | ||
|
|
||
| /// Paths to directories where application specific data can be stored. | ||
| /// These paths typically reside on external storage like separate partitions | ||
| /// or SD cards. Phones may have multiple storage directories available. | ||
| Future<List<String>> getExternalStoragePaths({ | ||
| /// Optional parameter. See [AndroidStorageDirectory] for more informations on | ||
| /// how this type translates to Android storage directories. | ||
| AndroidStorageDirectory type, | ||
| }) { | ||
| throw UnimplementedError( | ||
| 'getExternalStoragePaths() has not been implemented.'); | ||
| } | ||
|
|
||
| /// Path to the directory where downloaded files can be stored. | ||
| /// This is typically only relevant on desktop operating systems. | ||
| Future<String> getDownloadsPath() { | ||
| throw UnimplementedError('getDownloadsPath() has not been implemented.'); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /// Corresponds to constants defined in Androids `android.os.Environment` class. | ||
| /// | ||
| /// https://developer.android.com/reference/android/os/Environment.html#fields_1 | ||
| enum AndroidStorageDirectory { | ||
| /// Contains audio files that should be treated as music. | ||
| /// | ||
| /// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_MUSIC. | ||
| music, | ||
|
|
||
| /// Contains audio files that should be treated as podcasts. | ||
| /// | ||
| /// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_PODCASTS. | ||
| podcasts, | ||
|
|
||
| /// Contains audio files that should be treated as ringtones. | ||
| /// | ||
| /// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_RINGTONES. | ||
| ringtones, | ||
|
|
||
| /// Contains audio files that should be treated as alarm sounds. | ||
| /// | ||
| /// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_ALARMS. | ||
| alarms, | ||
|
|
||
| /// Contains audio files that should be treated as notification sounds. | ||
| /// | ||
| /// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_NOTIFICATIONS. | ||
| notifications, | ||
|
|
||
| /// Contains images. See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_PICTURES. | ||
| pictures, | ||
|
|
||
| /// Contains movies. See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_MOVIES. | ||
| movies, | ||
|
|
||
| /// Contains files of any type that have been downloaded by the user. | ||
| /// | ||
| /// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_DOWNLOADS. | ||
| downloads, | ||
|
|
||
| /// Used to hold both pictures and videos when the device filesystem is | ||
| /// treated like a camera's. | ||
| /// | ||
| /// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_DCIM. | ||
| dcim, | ||
|
|
||
| /// Holds user-created documents. See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_DOCUMENTS. | ||
| documents, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| // Copyright 2020 The Chromium 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 'dart:async'; | ||
|
|
||
| import 'enums.dart'; | ||
|
|
||
| import 'package:flutter/services.dart'; | ||
| import 'package:meta/meta.dart'; | ||
| import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; | ||
| import 'package:platform/platform.dart'; | ||
|
|
||
| /// An implementation of [PathProviderPlatform] that uses method channels. | ||
| class MethodChannelPathProvider extends PathProviderPlatform { | ||
| /// The method channel used to interact with the native platform. | ||
| @visibleForTesting | ||
| MethodChannel methodChannel = | ||
| MethodChannel('plugins.flutter.io/path_provider'); | ||
|
|
||
| // Ideally, this property shouldn't exist, and each platform should | ||
| // just implement the supported methods. Once all the platforms are | ||
| // federated, this property should be removed. | ||
| Platform _platform = const LocalPlatform(); | ||
|
|
||
| /// This API is only exposed for the unit tests. It should not be used by | ||
| /// any code outside of the plugin itself. | ||
| @visibleForTesting | ||
| void setMockPathProviderPlatform(Platform platform) { | ||
| _platform = platform; | ||
| } | ||
|
|
||
| Future<String> getTemporaryPath() { | ||
| return methodChannel.invokeMethod<String>('getTemporaryDirectory'); | ||
| } | ||
|
|
||
| Future<String> getApplicationSupportPath() { | ||
| return methodChannel.invokeMethod<String>('getApplicationSupportDirectory'); | ||
| } | ||
|
|
||
| Future<String> getLibraryPath() { | ||
| if (!_platform.isIOS && !_platform.isMacOS) { | ||
| throw UnsupportedError('Functionality only available on iOS/macOS'); | ||
| } | ||
| return methodChannel.invokeMethod<String>('getLibraryDirectory'); | ||
| } | ||
|
|
||
| Future<String> getApplicationDocumentsPath() { | ||
| return methodChannel | ||
| .invokeMethod<String>('getApplicationDocumentsDirectory'); | ||
| } | ||
|
|
||
| Future<String> getExternalStoragePath() { | ||
| if (!_platform.isAndroid) { | ||
| throw UnsupportedError('Functionality only available on Android'); | ||
| } | ||
| return methodChannel.invokeMethod<String>('getStorageDirectory'); | ||
| } | ||
|
|
||
| Future<List<String>> getExternalCachePaths() { | ||
| if (!_platform.isAndroid) { | ||
| throw UnsupportedError('Functionality only available on Android'); | ||
| } | ||
| return methodChannel | ||
| .invokeListMethod<String>('getExternalCacheDirectories'); | ||
| } | ||
|
|
||
| Future<List<String>> getExternalStoragePaths({ | ||
| AndroidStorageDirectory type, | ||
| }) async { | ||
| if (!_platform.isAndroid) { | ||
| throw UnsupportedError('Functionality only available on Android'); | ||
| } | ||
| return methodChannel.invokeListMethod<String>( | ||
| 'getExternalStorageDirectories', | ||
| <String, dynamic>{'type': type?.index}, | ||
| ); | ||
| } | ||
|
|
||
| Future<String> getDownloadsPath() { | ||
| if (!_platform.isMacOS) { | ||
| throw UnsupportedError('Functionality only available on macOS'); | ||
| } | ||
|
Comment on lines
+81
to
+83
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment I did in your previous platform interface migration. IMO this should be thrown by the Java side (I don't know what to do with the 'getDownloadsDirectory' call, and not in the MethodChannel implementation). If the Fuchsia version is able to fulfill this, this'd be throwing an exception before it even reaches native code.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I follow. I'm keeping it here to make sure it's as similar to the current implementation as possible. I think you are right about the fact that the native side would just return What do you mean by the fuchsia version example? In theory, nothing other than macOS should reach the native code. Maybe that's why the platform checks were added? To save some calls if we know they are going to fail? Also, maybe for testing :)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's agree to disagree :P
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| return methodChannel.invokeMethod<String>('getDownloadsDirectory'); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| name: path_provider_platform_interface | ||
| description: A common platform interface for the path_provider plugin. | ||
| homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_platform_interface | ||
| # NOTE: We strongly prefer non-breaking changes, even at the expense of a | ||
| # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes | ||
| version: 1.0.0 | ||
|
|
||
| dependencies: | ||
| flutter: | ||
| sdk: flutter | ||
| meta: ^1.0.5 | ||
| platform: ^2.0.0 | ||
| plugin_platform_interface: ^1.0.1 | ||
|
|
||
| dev_dependencies: | ||
| flutter_test: | ||
| sdk: flutter | ||
| pedantic: ^1.8.0 | ||
| test: any | ||
|
|
||
| environment: | ||
| sdk: ">=2.0.0-dev.28.0 <3.0.0" | ||
| flutter: ">=1.10.0 <2.0.0" |
Uh oh!
There was an error while loading. Please reload this page.