From 262c8547b06c30fe92435f766d4dda609bcd603b Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 16:35:05 -0700 Subject: [PATCH 01/18] Add support for getApplicationLibraryDirectory --- packages/path_provider/CHANGELOG.md | 4 ++ .../pathprovider/PathProviderPlugin.java | 7 ++++ .../example/test_driver/path_provider.dart | 10 +++++ .../ios/Classes/PathProviderPlugin.m | 6 +++ packages/path_provider/lib/path_provider.dart | 41 ++++++++++--------- packages/path_provider/pubspec.yaml | 2 +- .../test/path_provider_test.dart | 12 ++++++ 7 files changed, 62 insertions(+), 20 deletions(-) diff --git a/packages/path_provider/CHANGELOG.md b/packages/path_provider/CHANGELOG.md index c4c8e763f90d..1f174f4314ac 100644 --- a/packages/path_provider/CHANGELOG.md +++ b/packages/path_provider/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +* Added support for `getApplicationLibraryDirectory`. + ## 1.0.0 * Added integration tests. diff --git a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java index d56cb2b60ca1..1fa6f767ae24 100644 --- a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java +++ b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java @@ -32,6 +32,9 @@ public void onMethodCall(MethodCall call, Result result) { case "getTemporaryDirectory": result.success(getPathProviderTemporaryDirectory()); break; + case "getApplicationLibraryDirectory": + result.success(getPathProviderApplicationLibraryDirectory()); + break; case "getApplicationDocumentsDirectory": result.success(getPathProviderApplicationDocumentsDirectory()); break; @@ -47,6 +50,10 @@ private String getPathProviderTemporaryDirectory() { return mRegistrar.context().getCacheDir().getPath(); } + private String getPathProviderApplicationLibraryDirectory() { + return PathUtils.getDataDirectory(mRegistrar.context()); + } + private String getPathProviderApplicationDocumentsDirectory() { return PathUtils.getDataDirectory(mRegistrar.context()); } diff --git a/packages/path_provider/example/test_driver/path_provider.dart b/packages/path_provider/example/test_driver/path_provider.dart index c0c623747d17..033815cfea5e 100644 --- a/packages/path_provider/example/test_driver/path_provider.dart +++ b/packages/path_provider/example/test_driver/path_provider.dart @@ -35,6 +35,16 @@ void main() { file.deleteSync(); }); + test('getApplicationLibraryDirectory', () async { + final Directory result = await getApplicationLibraryDirectory(); + final String uuid = Uuid().v1(); + final File file = File('${result.path}/$uuid.txt'); + file.writeAsStringSync('Hello world!'); + expect(file.readAsStringSync(), 'Hello world!'); + expect(result.listSync(), isNotEmpty); + file.deleteSync(); + }); + test('getExternalStorageDirectory', () async { if (Platform.isIOS) { final Future result = getExternalStorageDirectory(); diff --git a/packages/path_provider/ios/Classes/PathProviderPlugin.m b/packages/path_provider/ios/Classes/PathProviderPlugin.m index 3e82e081bf6d..416d0a38d8e3 100644 --- a/packages/path_provider/ios/Classes/PathProviderPlugin.m +++ b/packages/path_provider/ios/Classes/PathProviderPlugin.m @@ -20,6 +20,8 @@ + (void)registerWithRegistrar:(NSObject*)registrar { result([self getTemporaryDirectory]); } else if ([@"getApplicationDocumentsDirectory" isEqualToString:call.method]) { result([self getApplicationDocumentsDirectory]); + } else if ([@"getApplicationLibraryDirectory" isEqualToString:call.method]) { + result([self getApplicationLibraryDirectory]); } else { result(FlutterMethodNotImplemented); } @@ -34,4 +36,8 @@ + (NSString*)getApplicationDocumentsDirectory { return GetDirectoryOfType(NSDocumentDirectory); } ++ (NSString*)getApplicationLibraryDirectory { + return GetDirectoryOfType(NSApplicationSupportDirectory); +} + @end diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 1875f7436d8b..4fe7ae030509 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -21,29 +21,35 @@ const MethodChannel _channel = /// /// On Android, this uses the `getCacheDir` API on the context. Future getTemporaryDirectory() async { - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - final String path = await _channel.invokeMethod('getTemporaryDirectory'); + final String path = await _channel.invokeMethod('getTemporaryDirectory'); if (path == null) { return null; } return Directory(path); } -/// Path to a directory where the application may place files that are private -/// to the application and will only be cleared when the application itself -/// is deleted. +/// Path to a directory where the application may place non-user-generated files +/// that can be downloaded again or regenerated. /// -/// On iOS, this uses the `NSDocumentsDirectory` API. +/// On iOS, this uses the `NSApplicationSupportDirectory` API. /// -/// On Android, this returns the AppData directory. +/// On Android, this uses the `getDataDirectory` API on the context. +Future getApplicationLibraryDirectory() async { + final String path = await _channel.invokeMethod('getApplicationLibraryDirectory'); + if (path == null) { + return null; + } + return Directory(path); +} + +/// 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. +/// +/// On Android, this uses the `getDataDirectory` API on the context. Future getApplicationDocumentsDirectory() async { - final String path = - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - await _channel.invokeMethod('getApplicationDocumentsDirectory'); + final String path = await _channel.invokeMethod('getApplicationDocumentsDirectory'); if (path == null) { return null; } @@ -57,14 +63,11 @@ Future getApplicationDocumentsDirectory() async { /// On iOS, this function throws an UnsupportedError as it is not possible /// to access outside the app's sandbox. /// -/// On Android this returns getExternalStorageDirectory. +/// On Android this returns the external storage directory. Future getExternalStorageDirectory() async { if (Platform.isIOS) throw UnsupportedError("Functionality not available on iOS"); - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - final String path = await _channel.invokeMethod('getStorageDirectory'); + final String path = await _channel.invokeMethod('getStorageDirectory'); if (path == null) { return null; } diff --git a/packages/path_provider/pubspec.yaml b/packages/path_provider/pubspec.yaml index 9913857e150f..3a16cefbe863 100644 --- a/packages/path_provider/pubspec.yaml +++ b/packages/path_provider/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for getting commonly used locations on the Android & iOS file systems, such as the temp and app data directories. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider -version: 1.0.0 +version: 1.0.1 flutter: plugin: diff --git a/packages/path_provider/test/path_provider_test.dart b/packages/path_provider/test/path_provider_test.dart index f1d1ff3451d3..8732f60be9b5 100644 --- a/packages/path_provider/test/path_provider_test.dart +++ b/packages/path_provider/test/path_provider_test.dart @@ -45,6 +45,18 @@ void main() { expect(directory, isNull); }); + test('getApplicationLibraryDirectory test', () async { + response = null; + final Directory directory = await getApplicationLibraryDirectory(); + expect( + log, + [ + isMethodCall('getApplicationLibraryDirectory', arguments: null) + ], + ); + expect(directory, isNull); + }); + test('TemporaryDirectory path test', () async { final String fakePath = "/foo/bar/baz"; response = fakePath; From 6137a87c8cbe8184f576f5903a54fece318f84ee Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 16:35:38 -0700 Subject: [PATCH 02/18] Reformat --- packages/path_provider/lib/path_provider.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 4fe7ae030509..98c7599785c8 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -21,7 +21,8 @@ const MethodChannel _channel = /// /// On Android, this uses the `getCacheDir` API on the context. Future getTemporaryDirectory() async { - final String path = await _channel.invokeMethod('getTemporaryDirectory'); + final String path = + await _channel.invokeMethod('getTemporaryDirectory'); if (path == null) { return null; } @@ -35,7 +36,8 @@ Future getTemporaryDirectory() async { /// /// On Android, this uses the `getDataDirectory` API on the context. Future getApplicationLibraryDirectory() async { - final String path = await _channel.invokeMethod('getApplicationLibraryDirectory'); + final String path = + await _channel.invokeMethod('getApplicationLibraryDirectory'); if (path == null) { return null; } @@ -49,7 +51,8 @@ Future getApplicationLibraryDirectory() async { /// /// On Android, this uses the `getDataDirectory` API on the context. Future getApplicationDocumentsDirectory() async { - final String path = await _channel.invokeMethod('getApplicationDocumentsDirectory'); + final String path = + await _channel.invokeMethod('getApplicationDocumentsDirectory'); if (path == null) { return null; } @@ -67,7 +70,8 @@ Future getApplicationDocumentsDirectory() async { Future getExternalStorageDirectory() async { if (Platform.isIOS) throw UnsupportedError("Functionality not available on iOS"); - final String path = await _channel.invokeMethod('getStorageDirectory'); + final String path = + await _channel.invokeMethod('getStorageDirectory'); if (path == null) { return null; } From 846cf49ebd68293efd83eae211ef3b2c7f09eb15 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 16:46:33 -0700 Subject: [PATCH 03/18] Rename ApplicationLibrary directory to ApplicationSupportDirectory --- packages/path_provider/CHANGELOG.md | 1 + .../plugins/pathprovider/PathProviderPlugin.java | 10 +++++----- .../example/test_driver/path_provider.dart | 10 +++++----- packages/path_provider/lib/path_provider.dart | 11 +++++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/path_provider/CHANGELOG.md b/packages/path_provider/CHANGELOG.md index 1f174f4314ac..4938faf33090 100644 --- a/packages/path_provider/CHANGELOG.md +++ b/packages/path_provider/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.0.1 * Added support for `getApplicationLibraryDirectory`. +* `getApplicationDocumentsDirectory` now uses external storage on Android. ## 1.0.0 diff --git a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java index 1fa6f767ae24..7effaadba41d 100644 --- a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java +++ b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java @@ -32,12 +32,12 @@ public void onMethodCall(MethodCall call, Result result) { case "getTemporaryDirectory": result.success(getPathProviderTemporaryDirectory()); break; - case "getApplicationLibraryDirectory": - result.success(getPathProviderApplicationLibraryDirectory()); - break; case "getApplicationDocumentsDirectory": result.success(getPathProviderApplicationDocumentsDirectory()); break; + case "getApplicationSupportDirectory": + result.success(getPathProviderApplicationSupportDirectory()); + break; case "getStorageDirectory": result.success(getPathProviderStorageDirectory()); break; @@ -50,11 +50,11 @@ private String getPathProviderTemporaryDirectory() { return mRegistrar.context().getCacheDir().getPath(); } - private String getPathProviderApplicationLibraryDirectory() { + private String getPathProviderApplicationDocumentsDirectory() { return PathUtils.getDataDirectory(mRegistrar.context()); } - private String getPathProviderApplicationDocumentsDirectory() { + private String getPathProviderApplicationSupportDirectory() { return PathUtils.getDataDirectory(mRegistrar.context()); } diff --git a/packages/path_provider/example/test_driver/path_provider.dart b/packages/path_provider/example/test_driver/path_provider.dart index 033815cfea5e..4315ffb15024 100644 --- a/packages/path_provider/example/test_driver/path_provider.dart +++ b/packages/path_provider/example/test_driver/path_provider.dart @@ -15,7 +15,7 @@ void main() { enableFlutterDriverExtension(handler: (_) => allTestsCompleter.future); tearDownAll(() => allTestsCompleter.complete(null)); - test('getTemporaryDirectory', () async { + test('$getTemporaryDirectory', () async { final Directory result = await getTemporaryDirectory(); final String uuid = Uuid().v1(); final File file = File('${result.path}/$uuid.txt'); @@ -25,7 +25,7 @@ void main() { file.deleteSync(); }); - test('getApplicationDocumentsDirectory', () async { + test('$getApplicationDocumentsDirectory', () async { final Directory result = await getApplicationDocumentsDirectory(); final String uuid = Uuid().v1(); final File file = File('${result.path}/$uuid.txt'); @@ -35,8 +35,8 @@ void main() { file.deleteSync(); }); - test('getApplicationLibraryDirectory', () async { - final Directory result = await getApplicationLibraryDirectory(); + test('$getApplicationSupportDirectory', () async { + final Directory result = await getApplicationSupportDirectory(); final String uuid = Uuid().v1(); final File file = File('${result.path}/$uuid.txt'); file.writeAsStringSync('Hello world!'); @@ -45,7 +45,7 @@ void main() { file.deleteSync(); }); - test('getExternalStorageDirectory', () async { + test('$getExternalStorageDirectory', () async { if (Platform.isIOS) { final Future result = getExternalStorageDirectory(); expect(result, throwsA(isInstanceOf())); diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 98c7599785c8..0256e807b113 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -29,15 +29,18 @@ Future getTemporaryDirectory() async { return Directory(path); } -/// Path to a directory where the application may place non-user-generated files -/// that can be downloaded again or regenerated. +/// Path to a directory where the application may place application support +/// files. +/// +/// 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. /// /// On Android, this uses the `getDataDirectory` API on the context. -Future getApplicationLibraryDirectory() async { +Future getApplicationSupportDirectory() async { final String path = - await _channel.invokeMethod('getApplicationLibraryDirectory'); + await _channel.invokeMethod('getApplicationSupportDirectory'); if (path == null) { return null; } From a4794e06a41bf823f2a57e71a67d3d7002d5d3a6 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 17:10:06 -0700 Subject: [PATCH 04/18] Update example, changelog --- packages/path_provider/CHANGELOG.md | 5 +++-- packages/path_provider/example/lib/main.dart | 22 +++++++++++++++++++ .../ios/Classes/PathProviderPlugin.m | 6 ++--- packages/path_provider/lib/path_provider.dart | 4 +++- .../test/path_provider_test.dart | 6 ++--- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/packages/path_provider/CHANGELOG.md b/packages/path_provider/CHANGELOG.md index 4938faf33090..e1b674bae183 100644 --- a/packages/path_provider/CHANGELOG.md +++ b/packages/path_provider/CHANGELOG.md @@ -1,7 +1,8 @@ ## 1.0.1 -* Added support for `getApplicationLibraryDirectory`. -* `getApplicationDocumentsDirectory` now uses external storage on Android. +* Added `getApplicationSupportDirectory`. +* Updated documentation for `getApplicationDocumentsDirectory` to suggest + using `getExternalStorageDirectory` on Android. ## 1.0.0 diff --git a/packages/path_provider/example/lib/main.dart b/packages/path_provider/example/lib/main.dart index 9311896128ba..a4a276c3cf7b 100644 --- a/packages/path_provider/example/lib/main.dart +++ b/packages/path_provider/example/lib/main.dart @@ -35,6 +35,7 @@ class MyHomePage extends StatefulWidget { class _MyHomePageState extends State { Future _tempDirectory; + Future _appSupportDirectory; Future _appDocumentsDirectory; Future _externalDocumentsDirectory; @@ -65,6 +66,12 @@ class _MyHomePageState extends State { }); } + void _requestAppSupportDirectory() { + setState(() { + _appDocumentsDirectory = getApplicationSupportDirectory(); + }); + } + void _requestExternalStorageDirectory() { setState(() { _externalDocumentsDirectory = getExternalStorageDirectory(); @@ -111,6 +118,21 @@ class _MyHomePageState extends State { child: FutureBuilder( future: _appDocumentsDirectory, builder: _buildDirectory), ), + Column( + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: RaisedButton( + child: const Text('Get Application Support Directory'), + onPressed: _requestAppSupportDirectory, + ), + ), + ], + ), + Expanded( + child: FutureBuilder( + future: _appSupportDirectory, builder: _buildDirectory), + ), Column(children: [ Padding( padding: const EdgeInsets.all(16.0), diff --git a/packages/path_provider/ios/Classes/PathProviderPlugin.m b/packages/path_provider/ios/Classes/PathProviderPlugin.m index 416d0a38d8e3..7cb46eac975b 100644 --- a/packages/path_provider/ios/Classes/PathProviderPlugin.m +++ b/packages/path_provider/ios/Classes/PathProviderPlugin.m @@ -20,8 +20,8 @@ + (void)registerWithRegistrar:(NSObject*)registrar { result([self getTemporaryDirectory]); } else if ([@"getApplicationDocumentsDirectory" isEqualToString:call.method]) { result([self getApplicationDocumentsDirectory]); - } else if ([@"getApplicationLibraryDirectory" isEqualToString:call.method]) { - result([self getApplicationLibraryDirectory]); + } else if ([@"getApplicationSupportDirectory" isEqualToString:call.method]) { + result([self getApplicationSupportDirectory]); } else { result(FlutterMethodNotImplemented); } @@ -36,7 +36,7 @@ + (NSString*)getApplicationDocumentsDirectory { return GetDirectoryOfType(NSDocumentDirectory); } -+ (NSString*)getApplicationLibraryDirectory { ++ (NSString*)getApplicationSupportDirectory { return GetDirectoryOfType(NSApplicationSupportDirectory); } diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 0256e807b113..4766e1acad00 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -52,7 +52,9 @@ Future getApplicationSupportDirectory() async { /// /// On iOS, this uses the `NSDocumentDirectory` API. /// -/// On Android, this uses the `getDataDirectory` API on the context. +/// On Android, this uses the `getDataDirectory` API on the context. Consider +/// using getExternalStorageDirectory instead if data is intended to be visible +/// to the user. Future getApplicationDocumentsDirectory() async { final String path = await _channel.invokeMethod('getApplicationDocumentsDirectory'); diff --git a/packages/path_provider/test/path_provider_test.dart b/packages/path_provider/test/path_provider_test.dart index 8732f60be9b5..04c035902128 100644 --- a/packages/path_provider/test/path_provider_test.dart +++ b/packages/path_provider/test/path_provider_test.dart @@ -45,13 +45,13 @@ void main() { expect(directory, isNull); }); - test('getApplicationLibraryDirectory test', () async { + test('getApplicationSupportDirectory test', () async { response = null; - final Directory directory = await getApplicationLibraryDirectory(); + final Directory directory = await getApplicationSupportDirectory(); expect( log, [ - isMethodCall('getApplicationLibraryDirectory', arguments: null) + isMethodCall('getApplicationSupportDirectory', arguments: null) ], ); expect(directory, isNull); From ea6866ebb3e0fb56edd4fb7d1d7c873a435c41d3 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 17:11:26 -0700 Subject: [PATCH 05/18] Fix example --- packages/path_provider/example/lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/path_provider/example/lib/main.dart b/packages/path_provider/example/lib/main.dart index a4a276c3cf7b..db32f7b68e3a 100644 --- a/packages/path_provider/example/lib/main.dart +++ b/packages/path_provider/example/lib/main.dart @@ -68,7 +68,7 @@ class _MyHomePageState extends State { void _requestAppSupportDirectory() { setState(() { - _appDocumentsDirectory = getApplicationSupportDirectory(); + _appSupportDirectory = getApplicationSupportDirectory(); }); } From 87058c6764188384a8d735aa2993ca04f208c37b Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 17:22:32 -0700 Subject: [PATCH 06/18] Update comments and changelog --- packages/path_provider/CHANGELOG.md | 4 +++- packages/path_provider/lib/path_provider.dart | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/CHANGELOG.md b/packages/path_provider/CHANGELOG.md index e1b674bae183..f37ebd73543c 100644 --- a/packages/path_provider/CHANGELOG.md +++ b/packages/path_provider/CHANGELOG.md @@ -2,7 +2,9 @@ * Added `getApplicationSupportDirectory`. * Updated documentation for `getApplicationDocumentsDirectory` to suggest - using `getExternalStorageDirectory` on Android. + using `getApplicationSupportDirectory` on iOS and + `getExternalStorageDirectory` on Android. +* Updated integration tests and example to reflect the above changes. ## 1.0.0 diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 4766e1acad00..9c279eb70ce0 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -50,7 +50,8 @@ Future getApplicationSupportDirectory() 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. +/// On iOS, this uses the `NSDocumentDirectory` API. Consider using +/// [getApplicationSupportDirectory] instead 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 From 9f6b116f23819587490593731cd829facc7ce8d2 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 17:25:06 -0700 Subject: [PATCH 07/18] Be less cute with integration test --- .../path_provider/example/test_driver/path_provider.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/path_provider/example/test_driver/path_provider.dart b/packages/path_provider/example/test_driver/path_provider.dart index 4315ffb15024..08218af79506 100644 --- a/packages/path_provider/example/test_driver/path_provider.dart +++ b/packages/path_provider/example/test_driver/path_provider.dart @@ -15,7 +15,7 @@ void main() { enableFlutterDriverExtension(handler: (_) => allTestsCompleter.future); tearDownAll(() => allTestsCompleter.complete(null)); - test('$getTemporaryDirectory', () async { + test('getTemporaryDirectory', () async { final Directory result = await getTemporaryDirectory(); final String uuid = Uuid().v1(); final File file = File('${result.path}/$uuid.txt'); @@ -25,7 +25,7 @@ void main() { file.deleteSync(); }); - test('$getApplicationDocumentsDirectory', () async { + test('getApplicationDocumentsDirectory', () async { final Directory result = await getApplicationDocumentsDirectory(); final String uuid = Uuid().v1(); final File file = File('${result.path}/$uuid.txt'); @@ -35,7 +35,7 @@ void main() { file.deleteSync(); }); - test('$getApplicationSupportDirectory', () async { + test('getApplicationSupportDirectory', () async { final Directory result = await getApplicationSupportDirectory(); final String uuid = Uuid().v1(); final File file = File('${result.path}/$uuid.txt'); @@ -45,7 +45,7 @@ void main() { file.deleteSync(); }); - test('$getExternalStorageDirectory', () async { + test('getExternalStorageDirectory', () async { if (Platform.isIOS) { final Future result = getExternalStorageDirectory(); expect(result, throwsA(isInstanceOf())); From 41286c4b3816dd3f0a647ef504e017acea62da4a Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 17:28:04 -0700 Subject: [PATCH 08/18] Fix version --- packages/path_provider/CHANGELOG.md | 2 +- packages/path_provider/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/CHANGELOG.md b/packages/path_provider/CHANGELOG.md index f37ebd73543c..388d5934eb37 100644 --- a/packages/path_provider/CHANGELOG.md +++ b/packages/path_provider/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.0.1 +## 1.1.0 * Added `getApplicationSupportDirectory`. * Updated documentation for `getApplicationDocumentsDirectory` to suggest diff --git a/packages/path_provider/pubspec.yaml b/packages/path_provider/pubspec.yaml index 3a16cefbe863..73b061924df3 100644 --- a/packages/path_provider/pubspec.yaml +++ b/packages/path_provider/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for getting commonly used locations on the Android & iOS file systems, such as the temp and app data directories. author: Flutter Team homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider -version: 1.0.1 +version: 1.1.0 flutter: plugin: From 9fac6e13fa0ae607dc6a714e0300f23f48896b07 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 3 May 2019 17:39:35 -0700 Subject: [PATCH 09/18] Update docs for getTemporaryDirectory --- packages/path_provider/CHANGELOG.md | 2 ++ packages/path_provider/lib/path_provider.dart | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/path_provider/CHANGELOG.md b/packages/path_provider/CHANGELOG.md index 388d5934eb37..3314f3872d35 100644 --- a/packages/path_provider/CHANGELOG.md +++ b/packages/path_provider/CHANGELOG.md @@ -4,6 +4,8 @@ * Updated documentation for `getApplicationDocumentsDirectory` to suggest using `getApplicationSupportDirectory` on iOS and `getExternalStorageDirectory` on Android. +* Updated documentation for `getTemporaryDirectory` to suggest using it + for caches of files that do not need to be backed up. * Updated integration tests and example to reflect the above changes. ## 1.0.0 diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 9c279eb70ce0..677fda6cdf67 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -10,7 +10,8 @@ import 'package:flutter/services.dart'; const MethodChannel _channel = MethodChannel('plugins.flutter.io/path_provider'); -/// Path to the temporary directory on the device. +/// Path to the temporary directory on the device that is not backed up and is +/// suitable for storing caches of downloaded files. /// /// Files in this directory may be cleared at any time. This does *not* return /// a new temporary directory. Instead, the caller is responsible for creating From 19413bf7d454021bf1201772ec6ee20119d8e49a Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 6 May 2019 08:03:43 -0700 Subject: [PATCH 10/18] Create the directory if it's not there --- packages/path_provider/lib/path_provider.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 677fda6cdf67..240a42e4dec0 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -39,13 +39,18 @@ Future getTemporaryDirectory() async { /// On iOS, this uses the `NSApplicationSupportDirectory` API. /// /// On Android, this uses the `getDataDirectory` API on the context. +/// +/// If the directory does not exist, it will be created. Future getApplicationSupportDirectory() async { final String path = await _channel.invokeMethod('getApplicationSupportDirectory'); if (path == null) { return null; } - return Directory(path); + Directory result = Directory(path); + if (!result.existsSync()) + result.createSync(); + return result; } /// Path to a directory where the application may place data that is From c6c265ff58f4eeff56cbf1be84dac0d9a3dce7c4 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 6 May 2019 08:16:24 -0700 Subject: [PATCH 11/18] Less automatic for the application support API. --- .../path_provider/example/test_driver/path_provider.dart | 2 ++ packages/path_provider/lib/path_provider.dart | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/path_provider/example/test_driver/path_provider.dart b/packages/path_provider/example/test_driver/path_provider.dart index 08218af79506..427aae6f7451 100644 --- a/packages/path_provider/example/test_driver/path_provider.dart +++ b/packages/path_provider/example/test_driver/path_provider.dart @@ -37,6 +37,8 @@ void main() { test('getApplicationSupportDirectory', () async { final Directory result = await getApplicationSupportDirectory(); + if (!result.existsSync()) + result.createSync(); final String uuid = Uuid().v1(); final File file = File('${result.path}/$uuid.txt'); file.writeAsStringSync('Hello world!'); diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 240a42e4dec0..cb570a8e8204 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -37,10 +37,10 @@ Future getTemporaryDirectory() async { /// use this directory for user data files. /// /// On iOS, this uses the `NSApplicationSupportDirectory` API. +/// This directory is not guaranteed to exist and you can call `createSync` to +/// create it if it doesn't exist. /// /// On Android, this uses the `getDataDirectory` API on the context. -/// -/// If the directory does not exist, it will be created. Future getApplicationSupportDirectory() async { final String path = await _channel.invokeMethod('getApplicationSupportDirectory'); @@ -48,8 +48,6 @@ Future getApplicationSupportDirectory() async { return null; } Directory result = Directory(path); - if (!result.existsSync()) - result.createSync(); return result; } From a8fa58f36e2a16f67422ca0c5a6710244a75c62c Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 6 May 2019 09:59:14 -0700 Subject: [PATCH 12/18] analyzer --- packages/path_provider/lib/path_provider.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index cb570a8e8204..a356d8856458 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -47,8 +47,7 @@ Future getApplicationSupportDirectory() async { if (path == null) { return null; } - Directory result = Directory(path); - return result; + return Directory(path); } /// Path to a directory where the application may place data that is From 013dd57efb971d3db5169e72fcb7f3cd29a60cb4 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 8 May 2019 12:22:43 -0700 Subject: [PATCH 13/18] Remove failing unit test and update API per feedback --- .../pathprovider/PathProviderPlugin.java | 7 ------ .../example/test_driver/path_provider.dart | 23 +++++++++++-------- packages/path_provider/lib/path_provider.dart | 13 ++++++----- .../test/path_provider_test.dart | 12 ---------- 4 files changed, 21 insertions(+), 34 deletions(-) diff --git a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java index 7effaadba41d..d56cb2b60ca1 100644 --- a/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java +++ b/packages/path_provider/android/src/main/java/io/flutter/plugins/pathprovider/PathProviderPlugin.java @@ -35,9 +35,6 @@ public void onMethodCall(MethodCall call, Result result) { case "getApplicationDocumentsDirectory": result.success(getPathProviderApplicationDocumentsDirectory()); break; - case "getApplicationSupportDirectory": - result.success(getPathProviderApplicationSupportDirectory()); - break; case "getStorageDirectory": result.success(getPathProviderStorageDirectory()); break; @@ -54,10 +51,6 @@ private String getPathProviderApplicationDocumentsDirectory() { return PathUtils.getDataDirectory(mRegistrar.context()); } - private String getPathProviderApplicationSupportDirectory() { - return PathUtils.getDataDirectory(mRegistrar.context()); - } - private String getPathProviderStorageDirectory() { return Environment.getExternalStorageDirectory().getAbsolutePath(); } diff --git a/packages/path_provider/example/test_driver/path_provider.dart b/packages/path_provider/example/test_driver/path_provider.dart index 427aae6f7451..e216afa088d3 100644 --- a/packages/path_provider/example/test_driver/path_provider.dart +++ b/packages/path_provider/example/test_driver/path_provider.dart @@ -36,15 +36,20 @@ void main() { }); test('getApplicationSupportDirectory', () async { - final Directory result = await getApplicationSupportDirectory(); - if (!result.existsSync()) - result.createSync(); - final String uuid = Uuid().v1(); - final File file = File('${result.path}/$uuid.txt'); - file.writeAsStringSync('Hello world!'); - expect(file.readAsStringSync(), 'Hello world!'); - expect(result.listSync(), isNotEmpty); - file.deleteSync(); + if (Platform.isIOS) { + final Directory result = await getApplicationSupportDirectory(); + if (!result.existsSync()) + result.createSync(); + final String uuid = Uuid().v1(); + final File file = File('${result.path}/$uuid.txt'); + file.writeAsStringSync('Hello world!'); + expect(file.readAsStringSync(), 'Hello world!'); + expect(result.listSync(), isNotEmpty); + file.deleteSync(); + } else if (Platform.isAndroid) { + final Future result = getExternalStorageDirectory(); + expect(result, throwsA(isInstanceOf())); + } }); test('getExternalStorageDirectory', () async { diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index a356d8856458..6a3564d26252 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -37,13 +37,14 @@ Future getTemporaryDirectory() async { /// use this directory for user data files. /// /// On iOS, this uses the `NSApplicationSupportDirectory` API. -/// This directory is not guaranteed to exist and you can call `createSync` to -/// create it if it doesn't exist. +/// If this directory does not exist, it is created automatically. /// -/// On Android, this uses the `getDataDirectory` API on the context. +/// On Android, this function throws an [UnsupportedError]. Future getApplicationSupportDirectory() async { + if (!Platform.isIOS) + throw UnsupportedError("getApplicationSupportDirectory requires iOS"); final String path = - await _channel.invokeMethod('getApplicationSupportDirectory'); + await _channel.invokeMethod('getApplicationSupportDirectory'); if (path == null) { return null; } @@ -72,10 +73,10 @@ Future getApplicationDocumentsDirectory() async { /// 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 +/// On iOS, this function throws an [UnsupportedError] as it is not possible /// to access outside the app's sandbox. /// -/// On Android this returns the external storage directory. +/// On Android this uses the `getExternalStorageDirectory` API. Future getExternalStorageDirectory() async { if (Platform.isIOS) throw UnsupportedError("Functionality not available on iOS"); diff --git a/packages/path_provider/test/path_provider_test.dart b/packages/path_provider/test/path_provider_test.dart index 04c035902128..f1d1ff3451d3 100644 --- a/packages/path_provider/test/path_provider_test.dart +++ b/packages/path_provider/test/path_provider_test.dart @@ -45,18 +45,6 @@ void main() { expect(directory, isNull); }); - test('getApplicationSupportDirectory test', () async { - response = null; - final Directory directory = await getApplicationSupportDirectory(); - expect( - log, - [ - isMethodCall('getApplicationSupportDirectory', arguments: null) - ], - ); - expect(directory, isNull); - }); - test('TemporaryDirectory path test', () async { final String fakePath = "/foo/bar/baz"; response = fakePath; From d05ad85722ddafc0c620bb90b1b247f7c400f7c9 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 8 May 2019 12:35:32 -0700 Subject: [PATCH 14/18] Include the code that creates the path --- .../ios/Classes/PathProviderPlugin.m | 22 ++++++++++++++++++- packages/path_provider/lib/path_provider.dart | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/path_provider/ios/Classes/PathProviderPlugin.m b/packages/path_provider/ios/Classes/PathProviderPlugin.m index 7cb46eac975b..a7fc58dc6ad6 100644 --- a/packages/path_provider/ios/Classes/PathProviderPlugin.m +++ b/packages/path_provider/ios/Classes/PathProviderPlugin.m @@ -9,6 +9,13 @@ return paths.firstObject; } +static FlutterError *getFlutterError(NSError *error) { + if (error == nil) return nil; + return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %ld", error.code] + message:error.domain + details:error.localizedDescription]; +} + @implementation FLTPathProviderPlugin + (void)registerWithRegistrar:(NSObject*)registrar { @@ -21,7 +28,20 @@ + (void)registerWithRegistrar:(NSObject*)registrar { } else if ([@"getApplicationDocumentsDirectory" isEqualToString:call.method]) { result([self getApplicationDocumentsDirectory]); } else if ([@"getApplicationSupportDirectory" isEqualToString:call.method]) { - result([self getApplicationSupportDirectory]); + NSString *path = [self getApplicationSupportDirectory]; + + // Create the path if it doesn't exist + NSError *error; + BOOL success = [self + createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (!success) { + result(getFlutterError(error)); + } else { + result(path); + } } else { result(FlutterMethodNotImplemented); } diff --git a/packages/path_provider/lib/path_provider.dart b/packages/path_provider/lib/path_provider.dart index 6a3564d26252..08e35d68dd63 100644 --- a/packages/path_provider/lib/path_provider.dart +++ b/packages/path_provider/lib/path_provider.dart @@ -44,7 +44,7 @@ Future getApplicationSupportDirectory() async { if (!Platform.isIOS) throw UnsupportedError("getApplicationSupportDirectory requires iOS"); final String path = - await _channel.invokeMethod('getApplicationSupportDirectory'); + await _channel.invokeMethod('getApplicationSupportDirectory'); if (path == null) { return null; } From f0119421fbba5a7fad3f3f9bb37a8d0173fa3f78 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 8 May 2019 12:50:33 -0700 Subject: [PATCH 15/18] Fix test --- packages/path_provider/example/test_driver/path_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/path_provider/example/test_driver/path_provider.dart b/packages/path_provider/example/test_driver/path_provider.dart index e216afa088d3..d2f2aea4634a 100644 --- a/packages/path_provider/example/test_driver/path_provider.dart +++ b/packages/path_provider/example/test_driver/path_provider.dart @@ -47,7 +47,7 @@ void main() { expect(result.listSync(), isNotEmpty); file.deleteSync(); } else if (Platform.isAndroid) { - final Future result = getExternalStorageDirectory(); + final Future result = getApplicationSupportDirectory(); expect(result, throwsA(isInstanceOf())); } }); From 5778572e900491fb10260906b8dcb0f0f2a04a2f Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 8 May 2019 12:53:06 -0700 Subject: [PATCH 16/18] Reformat --- .../ios/Classes/PathProviderPlugin.m | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/path_provider/ios/Classes/PathProviderPlugin.m b/packages/path_provider/ios/Classes/PathProviderPlugin.m index a7fc58dc6ad6..0476a1072f04 100644 --- a/packages/path_provider/ios/Classes/PathProviderPlugin.m +++ b/packages/path_provider/ios/Classes/PathProviderPlugin.m @@ -9,7 +9,7 @@ return paths.firstObject; } -static FlutterError *getFlutterError(NSError *error) { +static FlutterError* getFlutterError(NSError* error) { if (error == nil) return nil; return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %ld", error.code] message:error.domain @@ -28,15 +28,14 @@ + (void)registerWithRegistrar:(NSObject*)registrar { } else if ([@"getApplicationDocumentsDirectory" isEqualToString:call.method]) { result([self getApplicationDocumentsDirectory]); } else if ([@"getApplicationSupportDirectory" isEqualToString:call.method]) { - NSString *path = [self getApplicationSupportDirectory]; - + NSString* path = [self getApplicationSupportDirectory]; + // Create the path if it doesn't exist - NSError *error; - BOOL success = [self - createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:&error]; + NSError* error; + BOOL success = [self createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; if (!success) { result(getFlutterError(error)); } else { From 0f2e80172ac8c8b93f25111cc9e729e4b1f4eda1 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 8 May 2019 15:38:47 -0700 Subject: [PATCH 17/18] Remove create from test --- packages/path_provider/example/test_driver/path_provider.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/path_provider/example/test_driver/path_provider.dart b/packages/path_provider/example/test_driver/path_provider.dart index d2f2aea4634a..2f225a7034d8 100644 --- a/packages/path_provider/example/test_driver/path_provider.dart +++ b/packages/path_provider/example/test_driver/path_provider.dart @@ -38,8 +38,6 @@ void main() { test('getApplicationSupportDirectory', () async { if (Platform.isIOS) { final Directory result = await getApplicationSupportDirectory(); - if (!result.existsSync()) - result.createSync(); final String uuid = Uuid().v1(); final File file = File('${result.path}/$uuid.txt'); file.writeAsStringSync('Hello world!'); From 6bc82c0a09c67a7e7a42267ff0ddefb5f6ece560 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Wed, 8 May 2019 15:40:45 -0700 Subject: [PATCH 18/18] Fix iOS implementation of creating directory --- packages/path_provider/ios/Classes/PathProviderPlugin.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/path_provider/ios/Classes/PathProviderPlugin.m b/packages/path_provider/ios/Classes/PathProviderPlugin.m index 0476a1072f04..d81d6c676deb 100644 --- a/packages/path_provider/ios/Classes/PathProviderPlugin.m +++ b/packages/path_provider/ios/Classes/PathProviderPlugin.m @@ -32,10 +32,11 @@ + (void)registerWithRegistrar:(NSObject*)registrar { // Create the path if it doesn't exist NSError* error; - BOOL success = [self createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:&error]; + NSFileManager* fileManager = [NSFileManager defaultManager]; + BOOL success = [fileManager createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; if (!success) { result(getFlutterError(error)); } else {