Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 1.0.0

* Initial release.
27 changes: 27 additions & 0 deletions packages/path_provider/path_provider_platform_interface/LICENSE
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.
26 changes: 26 additions & 0 deletions packages/path_provider/path_provider_platform_interface/README.md
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
Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 MissingImplementation. I think if we want that exception as opposed to the UnsupportedError that might be a bigger discussion to be consistent with the rest of the plugins.

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 :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's agree to disagree :P

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I don't have a strong posture on this at all :) It's mostly a "Want to change as little as possible from the way it already was". I think @amirh or @cyanglaz might have a better opinion on this.

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"
Loading