Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 458b524

Browse files
[path_provider] Create platform interface (#2553)
1 parent a6d408b commit 458b524

8 files changed

Lines changed: 519 additions & 0 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 1.0.0
2+
3+
* Initial release.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2020 The Chromium Authors. All rights reserved.
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions are
5+
// met:
6+
//
7+
// * Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
// * Redistributions in binary form must reproduce the above
10+
// copyright notice, this list of conditions and the following disclaimer
11+
// in the documentation and/or other materials provided with the
12+
// distribution.
13+
// * Neither the name of Google Inc. nor the names of its
14+
// contributors may be used to endorse or promote products derived from
15+
// this software without specific prior written permission.
16+
//
17+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# path_provider_platform_interface
2+
3+
A common platform interface for the [`path_provider`][1] plugin.
4+
5+
This interface allows platform-specific implementations of the `path_provider`
6+
plugin, as well as the plugin itself, to ensure they are supporting the
7+
same interface.
8+
9+
# Usage
10+
11+
To implement a new platform-specific implementation of `path_provider`, extend
12+
[`PathProviderPlatform`][2] with an implementation that performs the
13+
platform-specific behavior, and when you register your plugin, set the default
14+
`PathProviderPlatform` by calling
15+
`PathProviderPlatform.instance = MyPlatformPathProvider()`.
16+
17+
# Note on breaking changes
18+
19+
Strongly prefer non-breaking changes (such as adding a method to the interface)
20+
over breaking changes for this package.
21+
22+
See https://flutter.dev/go/platform-interface-breaking-changes for a discussion
23+
on why a less-clean interface is preferable to a breaking change.
24+
25+
[1]: ../
26+
[2]: lib/path_provider_platform_interface.dart
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2020 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'src/enums.dart';
8+
import 'src/method_channel_path_provider.dart';
9+
10+
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
11+
12+
export 'src/enums.dart';
13+
14+
/// The interface that implementations of path_provider must implement.
15+
///
16+
/// Platform implementations should extend this class rather than implement it as `PathProvider`
17+
/// does not consider newly added methods to be breaking changes. Extending this class
18+
/// (using `extends`) ensures that the subclass will get the default implementation, while
19+
/// platform implementations that `implements` this interface will be broken by newly added
20+
/// [PathProviderPlatform] methods.
21+
abstract class PathProviderPlatform extends PlatformInterface {
22+
/// Constructs a PathProviderPlatform.
23+
PathProviderPlatform() : super(token: _token);
24+
25+
static final Object _token = Object();
26+
27+
static PathProviderPlatform _instance = MethodChannelPathProvider();
28+
29+
/// The default instance of [PathProviderPlatform] to use.
30+
///
31+
/// Defaults to [MethodChannelPathProvider].
32+
static PathProviderPlatform get instance => _instance;
33+
34+
/// Platform-specific plugins should set this with their own platform-specific
35+
/// class that extends [PathProviderPlatform] when they register themselves.
36+
static set instance(PathProviderPlatform instance) {
37+
PlatformInterface.verifyToken(instance, _token);
38+
_instance = instance;
39+
}
40+
41+
/// Path to the temporary directory on the device that is not backed up and is
42+
/// suitable for storing caches of downloaded files.
43+
Future<String> getTemporaryPath() {
44+
throw UnimplementedError('getTemporaryPath() has not been implemented.');
45+
}
46+
47+
/// Path to a directory where the application may place application support
48+
/// files.
49+
Future<String> getApplicationSupportPath() {
50+
throw UnimplementedError(
51+
'getApplicationSupportPath() has not been implemented.');
52+
}
53+
54+
/// Path to the directory where application can store files that are persistent,
55+
/// backed up, and not visible to the user, such as sqlite.db.
56+
Future<String> getLibraryPath() {
57+
throw UnimplementedError('getLibraryPath() has not been implemented.');
58+
}
59+
60+
/// Path to a directory where the application may place data that is
61+
/// user-generated, or that cannot otherwise be recreated by your application.
62+
Future<String> getApplicationDocumentsPath() {
63+
throw UnimplementedError(
64+
'getApplicationDocumentsPath() has not been implemented.');
65+
}
66+
67+
/// Path to a directory where the application may access top level storage.
68+
/// The current operating system should be determined before issuing this
69+
/// function call, as this functionality is only available on Android.
70+
Future<String> getExternalStoragePath() {
71+
throw UnimplementedError(
72+
'getExternalStoragePath() has not been implemented.');
73+
}
74+
75+
/// Paths to directories where application specific external cache data can be
76+
/// stored. These paths typically reside on external storage like separate
77+
/// partitions or SD cards. Phones may have multiple storage directories
78+
/// available.
79+
Future<List<String>> getExternalCachePaths() {
80+
throw UnimplementedError(
81+
'getExternalCachePaths() has not been implemented.');
82+
}
83+
84+
/// Paths to directories where application specific data can be stored.
85+
/// These paths typically reside on external storage like separate partitions
86+
/// or SD cards. Phones may have multiple storage directories available.
87+
Future<List<String>> getExternalStoragePaths({
88+
/// Optional parameter. See [AndroidStorageDirectory] for more informations on
89+
/// how this type translates to Android storage directories.
90+
AndroidStorageDirectory type,
91+
}) {
92+
throw UnimplementedError(
93+
'getExternalStoragePaths() has not been implemented.');
94+
}
95+
96+
/// Path to the directory where downloaded files can be stored.
97+
/// This is typically only relevant on desktop operating systems.
98+
Future<String> getDownloadsPath() {
99+
throw UnimplementedError('getDownloadsPath() has not been implemented.');
100+
}
101+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/// Corresponds to constants defined in Androids `android.os.Environment` class.
2+
///
3+
/// https://developer.android.com/reference/android/os/Environment.html#fields_1
4+
enum AndroidStorageDirectory {
5+
/// Contains audio files that should be treated as music.
6+
///
7+
/// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_MUSIC.
8+
music,
9+
10+
/// Contains audio files that should be treated as podcasts.
11+
///
12+
/// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_PODCASTS.
13+
podcasts,
14+
15+
/// Contains audio files that should be treated as ringtones.
16+
///
17+
/// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_RINGTONES.
18+
ringtones,
19+
20+
/// Contains audio files that should be treated as alarm sounds.
21+
///
22+
/// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_ALARMS.
23+
alarms,
24+
25+
/// Contains audio files that should be treated as notification sounds.
26+
///
27+
/// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_NOTIFICATIONS.
28+
notifications,
29+
30+
/// Contains images. See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_PICTURES.
31+
pictures,
32+
33+
/// Contains movies. See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_MOVIES.
34+
movies,
35+
36+
/// Contains files of any type that have been downloaded by the user.
37+
///
38+
/// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_DOWNLOADS.
39+
downloads,
40+
41+
/// Used to hold both pictures and videos when the device filesystem is
42+
/// treated like a camera's.
43+
///
44+
/// See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_DCIM.
45+
dcim,
46+
47+
/// Holds user-created documents. See https://developer.android.com/reference/android/os/Environment.html#DIRECTORY_DOCUMENTS.
48+
documents,
49+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright 2020 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'enums.dart';
8+
9+
import 'package:flutter/services.dart';
10+
import 'package:meta/meta.dart';
11+
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
12+
import 'package:platform/platform.dart';
13+
14+
/// An implementation of [PathProviderPlatform] that uses method channels.
15+
class MethodChannelPathProvider extends PathProviderPlatform {
16+
/// The method channel used to interact with the native platform.
17+
@visibleForTesting
18+
MethodChannel methodChannel =
19+
MethodChannel('plugins.flutter.io/path_provider');
20+
21+
// Ideally, this property shouldn't exist, and each platform should
22+
// just implement the supported methods. Once all the platforms are
23+
// federated, this property should be removed.
24+
Platform _platform = const LocalPlatform();
25+
26+
/// This API is only exposed for the unit tests. It should not be used by
27+
/// any code outside of the plugin itself.
28+
@visibleForTesting
29+
void setMockPathProviderPlatform(Platform platform) {
30+
_platform = platform;
31+
}
32+
33+
Future<String> getTemporaryPath() {
34+
return methodChannel.invokeMethod<String>('getTemporaryDirectory');
35+
}
36+
37+
Future<String> getApplicationSupportPath() {
38+
return methodChannel.invokeMethod<String>('getApplicationSupportDirectory');
39+
}
40+
41+
Future<String> getLibraryPath() {
42+
if (!_platform.isIOS && !_platform.isMacOS) {
43+
throw UnsupportedError('Functionality only available on iOS/macOS');
44+
}
45+
return methodChannel.invokeMethod<String>('getLibraryDirectory');
46+
}
47+
48+
Future<String> getApplicationDocumentsPath() {
49+
return methodChannel
50+
.invokeMethod<String>('getApplicationDocumentsDirectory');
51+
}
52+
53+
Future<String> getExternalStoragePath() {
54+
if (!_platform.isAndroid) {
55+
throw UnsupportedError('Functionality only available on Android');
56+
}
57+
return methodChannel.invokeMethod<String>('getStorageDirectory');
58+
}
59+
60+
Future<List<String>> getExternalCachePaths() {
61+
if (!_platform.isAndroid) {
62+
throw UnsupportedError('Functionality only available on Android');
63+
}
64+
return methodChannel
65+
.invokeListMethod<String>('getExternalCacheDirectories');
66+
}
67+
68+
Future<List<String>> getExternalStoragePaths({
69+
AndroidStorageDirectory type,
70+
}) async {
71+
if (!_platform.isAndroid) {
72+
throw UnsupportedError('Functionality only available on Android');
73+
}
74+
return methodChannel.invokeListMethod<String>(
75+
'getExternalStorageDirectories',
76+
<String, dynamic>{'type': type?.index},
77+
);
78+
}
79+
80+
Future<String> getDownloadsPath() {
81+
if (!_platform.isMacOS) {
82+
throw UnsupportedError('Functionality only available on macOS');
83+
}
84+
return methodChannel.invokeMethod<String>('getDownloadsDirectory');
85+
}
86+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: path_provider_platform_interface
2+
description: A common platform interface for the path_provider plugin.
3+
homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider_platform_interface
4+
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
5+
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
6+
version: 1.0.0
7+
8+
dependencies:
9+
flutter:
10+
sdk: flutter
11+
meta: ^1.0.5
12+
platform: ^2.0.0
13+
plugin_platform_interface: ^1.0.1
14+
15+
dev_dependencies:
16+
flutter_test:
17+
sdk: flutter
18+
pedantic: ^1.8.0
19+
test: any
20+
21+
environment:
22+
sdk: ">=2.0.0-dev.28.0 <3.0.0"
23+
flutter: ">=1.10.0 <2.0.0"

0 commit comments

Comments
 (0)