Skip to content

Commit

Permalink
[path_provider] Switch to path_provider_foundation (flutter#6989)
Browse files Browse the repository at this point in the history
* [path_provider] Switch to `path_provider_foundation`

Switches to using the new combined `path_provider_foundation` for iOS
and macOS.

Also updates the code documentation to make it less Android and iOS
specific. The original goal was to make the documentation for
the download directory not be actively wrong for the new implementation,
but it seemed like a good time to fix 76427 more generally.
(The fact that the docs are kind of a mess because the API itself
is kind of a mess is now
flutter/flutter#118712.)

Fixes flutter/flutter#117941
Fixes flutter/flutter#76427

* Remove exclusion

* Update test expectations and README

* Update test expectations again, and update docs
  • Loading branch information
stuartmorgan authored and mauricioluz committed Jan 26, 2023
1 parent 22174d3 commit 576f7e9
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 66 deletions.
4 changes: 3 additions & 1 deletion packages/path_provider/path_provider/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## NEXT
## 2.0.12

* Switches to the new `path_provider_foundation` implementation package
for iOS and macOS.
* Updates code for `no_leading_underscores_for_local_identifiers` lint.
* Updates minimum Flutter version to 2.10.
* Fixes avoid_redundant_argument_values lint warnings and minor typos.
Expand Down
2 changes: 1 addition & 1 deletion packages/path_provider/path_provider/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Directories support by platform:
| External Storage | ✔️ ||| ❌️ | ❌️ |
| External Cache Directories | ✔️ ||| ❌️ | ❌️ |
| External Storage Directories | ✔️ ||| ❌️ | ❌️ |
| Downloads || | ✔️ | ✔️ | ✔️ |
| Downloads || ✔️ | ✔️ | ✔️ | ✔️ |

## Testing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,16 @@ void main() {
}

testWidgets('getDownloadsDirectory', (WidgetTester tester) async {
if (Platform.isIOS || Platform.isAndroid) {
if (Platform.isAndroid) {
final Future<Directory?> result = getDownloadsDirectory();
expect(result, throwsA(isInstanceOf<UnsupportedError>()));
} else {
final Directory? result = await getDownloadsDirectory();
if (Platform.isMacOS) {
// On recent versions of macOS, actually using the downloads directory
// requires a user prompt, so will fail on CI. Instead, just check that
// it returned a path with the expected directory name.
expect(result?.path, endsWith('Downloads'));
} else {
_verifySampleFile(result, 'downloads');
}
// On recent versions of macOS, actually using the downloads directory
// requires a user prompt (so will fail on CI), and on some platforms the
// directory may not exist. Instead of verifying that it exists, just
// check that it returned a path.
expect(result?.path, isNotEmpty);
}
});
}
Expand Down
96 changes: 52 additions & 44 deletions packages/path_provider/path_provider/lib/path_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ PathProviderPlatform get _platform => PathProviderPlatform.instance;
/// (and cleaning up) files or directories within this directory. This
/// directory is scoped to the calling application.
///
/// On iOS, this uses the `NSCachesDirectory` API.
/// Example implementations:
/// - `NSCachesDirectory` on iOS and macOS.
/// - `Context.getCacheDir` on Android.
///
/// On Android, this uses the `getCacheDir` API on the context.
///
/// Throws a `MissingPlatformDirectoryException` if the system is unable to
/// Throws a [MissingPlatformDirectoryException] if the system is unable to
/// provide the directory.
Future<Directory> getTemporaryDirectory() async {
final String? path = await _platform.getTemporaryPath();
Expand All @@ -63,15 +63,16 @@ Future<Directory> getTemporaryDirectory() async {
/// Path to a directory where the application may place application support
/// files.
///
/// If this directory does not exist, it is created automatically.
///
/// Use this for files you don’t want exposed to the user. Your app should not
/// use this directory for user data files.
///
/// On iOS, this uses the `NSApplicationSupportDirectory` API.
/// If this directory does not exist, it is created automatically.
///
/// On Android, this function uses the `getFilesDir` API on the context.
/// Example implementations:
/// - `NSApplicationSupportDirectory` on iOS and macOS.
/// - The Flutter engine's `PathUtils.getFilesDir` API on Android.
///
/// Throws a `MissingPlatformDirectoryException` if the system is unable to
/// Throws a [MissingPlatformDirectoryException] if the system is unable to
/// provide the directory.
Future<Directory> getApplicationSupportDirectory() async {
final String? path = await _platform.getApplicationSupportPath();
Expand All @@ -86,10 +87,14 @@ Future<Directory> getApplicationSupportDirectory() async {
/// Path to the directory where application can store files that are persistent,
/// backed up, and not visible to the user, such as sqlite.db.
///
/// On Android, this function throws an [UnsupportedError] as no equivalent
/// path exists.
/// Example implementations:
/// - `NSApplicationSupportDirectory` on iOS and macOS.
///
/// Throws an [UnsupportedError] if this is not supported on the current
/// platform. For example, this is unlikely to ever be supported on Android,
/// as no equivalent path exists.
///
/// Throws a `MissingPlatformDirectoryException` if the system is unable to
/// Throws a [MissingPlatformDirectoryException] if the system is unable to
/// provide the directory on a supported platform.
Future<Directory> getLibraryDirectory() async {
final String? path = await _platform.getLibraryPath();
Expand All @@ -102,14 +107,14 @@ Future<Directory> getLibraryDirectory() async {
/// Path to a directory where the application may place data that is
/// user-generated, or that cannot otherwise be recreated by your application.
///
/// On iOS, this uses the `NSDocumentDirectory` API. Consider using
/// [getApplicationSupportDirectory] instead if the data is not user-generated.
/// Consider using another path, such as [getApplicationSupportDirectory] or
/// [getExternalStorageDirectory], if the data is not user-generated.
///
/// On Android, this uses the `getDataDirectory` API on the context. Consider
/// using [getExternalStorageDirectory] instead if data is intended to be visible
/// to the user.
/// Example implementations:
/// - `NSDocumentDirectory` on iOS and macOS.
/// - The Flutter engine's `PathUtils.getDataDirectory` API on Android.
///
/// Throws a `MissingPlatformDirectoryException` if the system is unable to
/// Throws a [MissingPlatformDirectoryException] if the system is unable to
/// provide the directory.
Future<Directory> getApplicationDocumentsDirectory() async {
final String? path = await _platform.getApplicationDocumentsPath();
Expand All @@ -121,13 +126,13 @@ Future<Directory> getApplicationDocumentsDirectory() async {
}

/// 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.
///
/// On iOS, this function throws an [UnsupportedError] as it is not possible
/// to access outside the app's sandbox.
/// Example implementation:
/// - `getExternalFilesDir(null)` on Android.
///
/// On Android this uses the `getExternalFilesDir(null)`.
/// Throws an [UnsupportedError] if this is not supported on the current
/// platform (for example, on iOS where it is not possible to access outside
/// the app's sandbox).
Future<Directory?> getExternalStorageDirectory() async {
final String? path = await _platform.getExternalStoragePath();
if (path == null) {
Expand All @@ -136,19 +141,19 @@ Future<Directory?> getExternalStorageDirectory() async {
return Directory(path);
}

/// 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.
/// Paths to directories where application specific cache data can be stored
/// externally.
///
/// The current operating system should be determined before issuing this
/// function call, as this functionality is only available on Android.
/// These paths typically reside on external storage like separate partitions
/// or SD cards. Phones may have multiple storage directories available.
///
/// On iOS, this function throws an UnsupportedError as it is not possible
/// to access outside the app's sandbox.
/// Example implementation:
/// - Context.getExternalCacheDirs() on Android (or
/// Context.getExternalCacheDir() on API levels below 19).
///
/// On Android this returns Context.getExternalCacheDirs() or
/// Context.getExternalCacheDir() on API levels below 19.
/// Throws an [UnsupportedError] if this is not supported on the current
/// platform. This is unlikely to ever be supported on any platform other than
/// Android.
Future<List<Directory>?> getExternalCacheDirectories() async {
final List<String>? paths = await _platform.getExternalCachePaths();
if (paths == null) {
Expand All @@ -158,18 +163,19 @@ Future<List<Directory>?> getExternalCacheDirectories() async {
return paths.map((String path) => Directory(path)).toList();
}

/// Paths to directories where application specific data can be stored.
/// Paths to directories where application specific data can be stored
/// externally.
///
/// These paths typically reside on external storage like separate partitions
/// or SD cards. Phones may have multiple storage directories available.
///
/// The current operating system should be determined before issuing this
/// function call, as this functionality is only available on Android.
/// Example implementation:
/// - Context.getExternalFilesDirs(type) on Android (or
/// Context.getExternalFilesDir(type) on API levels below 19).
///
/// On iOS, this function throws an UnsupportedError as it is not possible
/// to access outside the app's sandbox.
///
/// On Android this returns Context.getExternalFilesDirs(String type) or
/// Context.getExternalFilesDir(String type) on API levels below 19.
/// Throws an [UnsupportedError] if this is not supported on the current
/// platform. This is unlikely to ever be supported on any platform other than
/// Android.
Future<List<Directory>?> getExternalStorageDirectories({
/// Optional parameter. See [StorageDirectory] for more informations on
/// how this type translates to Android storage directories.
Expand All @@ -185,10 +191,12 @@ Future<List<Directory>?> getExternalStorageDirectories({
}

/// Path to the directory where downloaded files can be stored.
/// This is typically only relevant on desktop operating systems.
///
/// On Android and on iOS, this function throws an [UnsupportedError] as no equivalent
/// path exists.
/// The returned directory is not guaranteed to exist, so clients should verify
/// that it does before using it, and potentially create it if necessary.
///
/// Throws an [UnsupportedError] if this is not supported on the current
/// platform.
Future<Directory?> getDownloadsDirectory() async {
final String? path = await _platform.getDownloadsPath();
if (path == null) {
Expand Down
11 changes: 5 additions & 6 deletions packages/path_provider/path_provider/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: path_provider
description: Flutter plugin for getting commonly used locations on host platform file systems, such as the temp and app data directories.
repository: https://github.com/flutter/plugins/tree/main/packages/path_provider/path_provider
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22
version: 2.0.11
version: 2.0.12

environment:
sdk: ">=2.14.0 <3.0.0"
Expand All @@ -14,21 +14,20 @@ flutter:
android:
default_package: path_provider_android
ios:
default_package: path_provider_ios
macos:
default_package: path_provider_macos
default_package: path_provider_foundation
linux:
default_package: path_provider_linux
macos:
default_package: path_provider_foundation
windows:
default_package: path_provider_windows

dependencies:
flutter:
sdk: flutter
path_provider_android: ^2.0.6
path_provider_ios: ^2.0.6
path_provider_foundation: ^2.1.0
path_provider_linux: ^2.0.1
path_provider_macos: ^2.0.0
path_provider_platform_interface: ^2.0.0
path_provider_windows: ^2.0.2

Expand Down
5 changes: 0 additions & 5 deletions script/configs/exclude_all_plugins_app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,3 @@

# This is a permament entry, as it should never be a direct app dependency.
- plugin_platform_interface
# Temporarily excluded to avoid runtime conflicts with
# path_provider_macos and _ios, which are still what path_provider
# uses. This will be removed when the switch to path_provider_foundation
# is complete. See https://github.com/flutter/flutter/issues/117941
- path_provider_foundation

0 comments on commit 576f7e9

Please sign in to comment.