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

Commit a7c074c

Browse files
[path_provider] add getApplicationSupportDirectory (#1566)
* Add support for getApplicationLibraryDirectory
1 parent 9298f1c commit a7c074c

File tree

6 files changed

+111
-21
lines changed

6 files changed

+111
-21
lines changed

packages/path_provider/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## 1.1.0
2+
3+
* Added `getApplicationSupportDirectory`.
4+
* Updated documentation for `getApplicationDocumentsDirectory` to suggest
5+
using `getApplicationSupportDirectory` on iOS and
6+
`getExternalStorageDirectory` on Android.
7+
* Updated documentation for `getTemporaryDirectory` to suggest using it
8+
for caches of files that do not need to be backed up.
9+
* Updated integration tests and example to reflect the above changes.
10+
111
## 1.0.0
212

313
* Added integration tests.

packages/path_provider/example/lib/main.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class MyHomePage extends StatefulWidget {
3535

3636
class _MyHomePageState extends State<MyHomePage> {
3737
Future<Directory> _tempDirectory;
38+
Future<Directory> _appSupportDirectory;
3839
Future<Directory> _appDocumentsDirectory;
3940
Future<Directory> _externalDocumentsDirectory;
4041

@@ -65,6 +66,12 @@ class _MyHomePageState extends State<MyHomePage> {
6566
});
6667
}
6768

69+
void _requestAppSupportDirectory() {
70+
setState(() {
71+
_appSupportDirectory = getApplicationSupportDirectory();
72+
});
73+
}
74+
6875
void _requestExternalStorageDirectory() {
6976
setState(() {
7077
_externalDocumentsDirectory = getExternalStorageDirectory();
@@ -111,6 +118,21 @@ class _MyHomePageState extends State<MyHomePage> {
111118
child: FutureBuilder<Directory>(
112119
future: _appDocumentsDirectory, builder: _buildDirectory),
113120
),
121+
Column(
122+
children: <Widget>[
123+
Padding(
124+
padding: const EdgeInsets.all(16.0),
125+
child: RaisedButton(
126+
child: const Text('Get Application Support Directory'),
127+
onPressed: _requestAppSupportDirectory,
128+
),
129+
),
130+
],
131+
),
132+
Expanded(
133+
child: FutureBuilder<Directory>(
134+
future: _appSupportDirectory, builder: _buildDirectory),
135+
),
114136
Column(children: <Widget>[
115137
Padding(
116138
padding: const EdgeInsets.all(16.0),

packages/path_provider/example/test_driver/path_provider.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,21 @@ void main() {
3535
file.deleteSync();
3636
});
3737

38+
test('getApplicationSupportDirectory', () async {
39+
if (Platform.isIOS) {
40+
final Directory result = await getApplicationSupportDirectory();
41+
final String uuid = Uuid().v1();
42+
final File file = File('${result.path}/$uuid.txt');
43+
file.writeAsStringSync('Hello world!');
44+
expect(file.readAsStringSync(), 'Hello world!');
45+
expect(result.listSync(), isNotEmpty);
46+
file.deleteSync();
47+
} else if (Platform.isAndroid) {
48+
final Future<Directory> result = getApplicationSupportDirectory();
49+
expect(result, throwsA(isInstanceOf<UnsupportedError>()));
50+
}
51+
});
52+
3853
test('getExternalStorageDirectory', () async {
3954
if (Platform.isIOS) {
4055
final Future<Directory> result = getExternalStorageDirectory();

packages/path_provider/ios/Classes/PathProviderPlugin.m

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
return paths.firstObject;
1010
}
1111

12+
static FlutterError* getFlutterError(NSError* error) {
13+
if (error == nil) return nil;
14+
return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %ld", error.code]
15+
message:error.domain
16+
details:error.localizedDescription];
17+
}
18+
1219
@implementation FLTPathProviderPlugin
1320

1421
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
@@ -20,6 +27,21 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
2027
result([self getTemporaryDirectory]);
2128
} else if ([@"getApplicationDocumentsDirectory" isEqualToString:call.method]) {
2229
result([self getApplicationDocumentsDirectory]);
30+
} else if ([@"getApplicationSupportDirectory" isEqualToString:call.method]) {
31+
NSString* path = [self getApplicationSupportDirectory];
32+
33+
// Create the path if it doesn't exist
34+
NSError* error;
35+
NSFileManager* fileManager = [NSFileManager defaultManager];
36+
BOOL success = [fileManager createDirectoryAtPath:path
37+
withIntermediateDirectories:YES
38+
attributes:nil
39+
error:&error];
40+
if (!success) {
41+
result(getFlutterError(error));
42+
} else {
43+
result(path);
44+
}
2345
} else {
2446
result(FlutterMethodNotImplemented);
2547
}
@@ -34,4 +56,8 @@ + (NSString*)getApplicationDocumentsDirectory {
3456
return GetDirectoryOfType(NSDocumentDirectory);
3557
}
3658

59+
+ (NSString*)getApplicationSupportDirectory {
60+
return GetDirectoryOfType(NSApplicationSupportDirectory);
61+
}
62+
3763
@end

packages/path_provider/lib/path_provider.dart

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import 'package:flutter/services.dart';
1010
const MethodChannel _channel =
1111
MethodChannel('plugins.flutter.io/path_provider');
1212

13-
/// Path to the temporary directory on the device.
13+
/// Path to the temporary directory on the device that is not backed up and is
14+
/// suitable for storing caches of downloaded files.
1415
///
1516
/// Files in this directory may be cleared at any time. This does *not* return
1617
/// a new temporary directory. Instead, the caller is responsible for creating
@@ -21,29 +22,47 @@ const MethodChannel _channel =
2122
///
2223
/// On Android, this uses the `getCacheDir` API on the context.
2324
Future<Directory> getTemporaryDirectory() async {
24-
// TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter.
25-
// https://github.com/flutter/flutter/issues/26431
26-
// ignore: strong_mode_implicit_dynamic_method
27-
final String path = await _channel.invokeMethod('getTemporaryDirectory');
25+
final String path =
26+
await _channel.invokeMethod<String>('getTemporaryDirectory');
27+
if (path == null) {
28+
return null;
29+
}
30+
return Directory(path);
31+
}
32+
33+
/// Path to a directory where the application may place application support
34+
/// files.
35+
///
36+
/// Use this for files you don’t want exposed to the user. Your app should not
37+
/// use this directory for user data files.
38+
///
39+
/// On iOS, this uses the `NSApplicationSupportDirectory` API.
40+
/// If this directory does not exist, it is created automatically.
41+
///
42+
/// On Android, this function throws an [UnsupportedError].
43+
Future<Directory> getApplicationSupportDirectory() async {
44+
if (!Platform.isIOS)
45+
throw UnsupportedError("getApplicationSupportDirectory requires iOS");
46+
final String path =
47+
await _channel.invokeMethod<String>('getApplicationSupportDirectory');
2848
if (path == null) {
2949
return null;
3050
}
3151
return Directory(path);
3252
}
3353

34-
/// Path to a directory where the application may place files that are private
35-
/// to the application and will only be cleared when the application itself
36-
/// is deleted.
54+
/// Path to a directory where the application may place data that is
55+
/// user-generated, or that cannot otherwise be recreated by your application.
3756
///
38-
/// On iOS, this uses the `NSDocumentsDirectory` API.
57+
/// On iOS, this uses the `NSDocumentDirectory` API. Consider using
58+
/// [getApplicationSupportDirectory] instead if the data is not user-generated.
3959
///
40-
/// On Android, this returns the AppData directory.
60+
/// On Android, this uses the `getDataDirectory` API on the context. Consider
61+
/// using getExternalStorageDirectory instead if data is intended to be visible
62+
/// to the user.
4163
Future<Directory> getApplicationDocumentsDirectory() async {
4264
final String path =
43-
// TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter.
44-
// https://github.com/flutter/flutter/issues/26431
45-
// ignore: strong_mode_implicit_dynamic_method
46-
await _channel.invokeMethod('getApplicationDocumentsDirectory');
65+
await _channel.invokeMethod<String>('getApplicationDocumentsDirectory');
4766
if (path == null) {
4867
return null;
4968
}
@@ -54,17 +73,15 @@ Future<Directory> getApplicationDocumentsDirectory() async {
5473
/// The current operating system should be determined before issuing this
5574
/// function call, as this functionality is only available on Android.
5675
///
57-
/// On iOS, this function throws an UnsupportedError as it is not possible
76+
/// On iOS, this function throws an [UnsupportedError] as it is not possible
5877
/// to access outside the app's sandbox.
5978
///
60-
/// On Android this returns getExternalStorageDirectory.
79+
/// On Android this uses the `getExternalStorageDirectory` API.
6180
Future<Directory> getExternalStorageDirectory() async {
6281
if (Platform.isIOS)
6382
throw UnsupportedError("Functionality not available on iOS");
64-
// TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter.
65-
// https://github.com/flutter/flutter/issues/26431
66-
// ignore: strong_mode_implicit_dynamic_method
67-
final String path = await _channel.invokeMethod('getStorageDirectory');
83+
final String path =
84+
await _channel.invokeMethod<String>('getStorageDirectory');
6885
if (path == null) {
6986
return null;
7087
}

packages/path_provider/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for getting commonly used locations on the Android &
33
iOS file systems, such as the temp and app data directories.
44
author: Flutter Team <[email protected]>
55
homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider
6-
version: 1.0.0
6+
version: 1.1.0
77

88
flutter:
99
plugin:

0 commit comments

Comments
 (0)