Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
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
4 changes: 4 additions & 0 deletions packages/path_provider/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.4.2

* Support Android devices with multiple external storage options.

## 0.4.1

* Updated Gradle tooling to match Android Studio 3.1.2.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@

package io.flutter.plugins.pathprovider;

import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Environment;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.util.PathUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class PathProviderPlugin implements MethodCallHandler {

private final Registrar mRegistrar;

public static void registerWith(Registrar registrar) {
Expand All @@ -38,6 +44,13 @@ public void onMethodCall(MethodCall call, Result result) {
case "getStorageDirectory":
result.success(getPathProviderStorageDirectory());
break;
case "getExternalCacheDirectories":
result.success(getPathProviderExternalCacheDirectories());
break;
case "getExternalStorageDirectories":
final String type = call.argument("type");
result.success(getPathProviderExternalStorageDirectories(type));
break;
default:
result.notImplemented();
}
Expand All @@ -54,4 +67,42 @@ private String getPathProviderApplicationDocumentsDirectory() {
private String getPathProviderStorageDirectory() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}

private List<String> getPathProviderExternalCacheDirectories() {
final List<String> paths = new ArrayList<>();

if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
for (File dir : mRegistrar.context().getExternalCacheDirs()) {
if (dir != null) {
paths.add(dir.getAbsolutePath());
}
}
} else {
File dir = mRegistrar.context().getExternalCacheDir();
if (dir != null) {
paths.add(dir.getAbsolutePath());
}
}

return paths;
}

private List<String> getPathProviderExternalStorageDirectories(String type) {
final List<String> paths = new ArrayList<>();

if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
for (File dir : mRegistrar.context().getExternalFilesDirs(type)) {
if (dir != null) {
paths.add(dir.getAbsolutePath());
}
}
} else {
File dir = mRegistrar.context().getExternalFilesDir(type);
if (dir != null) {
paths.add(dir.getAbsolutePath());
}
}

return paths;
}
}
80 changes: 66 additions & 14 deletions packages/path_provider/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class _MyHomePageState extends State<MyHomePage> {
Future<Directory> _tempDirectory;
Future<Directory> _appDocumentsDirectory;
Future<Directory> _externalDocumentsDirectory;
Future<List<Directory>> _externalStorageDirectories;
Future<List<Directory>> _externalCacheDirectories;

void _requestTempDirectory() {
setState(() {
Expand All @@ -59,6 +61,23 @@ class _MyHomePageState extends State<MyHomePage> {
return Padding(padding: const EdgeInsets.all(16.0), child: text);
}

Widget _buildDirectories(
BuildContext context, AsyncSnapshot<List<Directory>> snapshot) {
Text text = const Text('');
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
text = Text('Error: ${snapshot.error}');
} else if (snapshot.hasData) {
final String combined =
snapshot.data.map((Directory d) => d.path).join(', ');
text = Text('paths: $combined');
} else {
text = const Text('path unavailable');
}
}
return Padding(padding: const EdgeInsets.all(16.0), child: text);
}

void _requestAppDocumentsDirectory() {
setState(() {
_appDocumentsDirectory = getApplicationDocumentsDirectory();
Expand All @@ -71,13 +90,25 @@ class _MyHomePageState extends State<MyHomePage> {
});
}

void _requestExternalStorageDirectories(String type) {
setState(() {
_externalStorageDirectories = getExternalStorageDirectories(type);
});
}

void _requestExternalCacheDirectories() {
setState(() {
_externalCacheDirectories = getExternalCacheDirectories();
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expand All @@ -92,10 +123,8 @@ class _MyHomePageState extends State<MyHomePage> {
),
],
),
Expanded(
child: FutureBuilder<Directory>(
future: _tempDirectory, builder: _buildDirectory),
),
FutureBuilder<Directory>(
future: _tempDirectory, builder: _buildDirectory),
Column(
children: <Widget>[
Padding(
Expand All @@ -107,10 +136,8 @@ class _MyHomePageState extends State<MyHomePage> {
),
],
),
Expanded(
child: FutureBuilder<Directory>(
future: _appDocumentsDirectory, builder: _buildDirectory),
),
FutureBuilder<Directory>(
future: _appDocumentsDirectory, builder: _buildDirectory),
Column(children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
Expand All @@ -122,11 +149,36 @@ class _MyHomePageState extends State<MyHomePage> {
),
),
]),
Expanded(
child: FutureBuilder<Directory>(
future: _externalDocumentsDirectory,
builder: _buildDirectory),
),
FutureBuilder<Directory>(
future: _externalDocumentsDirectory, builder: _buildDirectory),
Column(children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: RaisedButton(
child: Text(
'${Platform.isIOS ? "External directories are unavailable " "on iOS" : "Get External Storage Directories"}'),
onPressed: Platform.isIOS
? null
: () => _requestExternalStorageDirectories(null),
),
),
]),
FutureBuilder<List<Directory>>(
future: _externalStorageDirectories,
builder: _buildDirectories),
Column(children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: RaisedButton(
child: Text(
'${Platform.isIOS ? "External directories are unavailable " "on iOS" : "Get External Cache Directories"}'),
onPressed:
Platform.isIOS ? null : _requestExternalCacheDirectories,
),
),
]),
FutureBuilder<List<Directory>>(
future: _externalCacheDirectories, builder: _buildDirectories),
],
),
),
Expand Down
48 changes: 48 additions & 0 deletions packages/path_provider/lib/path_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,51 @@ Future<Directory> getExternalStorageDirectory() async {
}
return Directory(path);
}

/// Paths to directories where application specific 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.
///
/// 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.
///
/// On Android this returns Context.getExternalCacheDirs() or
/// Context.getExternalCacheDir() on API levels below 19.
Future<List<Directory>> getExternalCacheDirectories() async {
if (Platform.isIOS)
throw UnsupportedError("Functionality not available on iOS");
final List<dynamic> paths =
await _channel.invokeMethod('getExternalCacheDirectories');

return paths.map((dynamic path) => Directory(path)).toList();
}

/// 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.
///
/// 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.
///
/// The parameter type is optional. If it is set, it must be one of the
/// "DIRECTORY" constants defined in `android.os.Environment`, e.g.
/// https://developer.android.com/reference/android/os/Environment#DIRECTORY_MUSIC
///
/// On Android this returns Context.getExternalFilesDirs(String type) or
/// Context.getExternalFilesDir(String type) on API levels below 19.
Future<List<Directory>> getExternalStorageDirectories(String type) async {
if (Platform.isIOS)
throw UnsupportedError("Functionality not available on iOS");
final List<dynamic> paths = await _channel.invokeMethod(
'getExternalStorageDirectories',
<String, String>{"type": type},
);

return paths.map((dynamic path) => Directory(path)).toList();
}
2 changes: 1 addition & 1 deletion packages/path_provider/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
homepage: https://github.com/flutter/plugins/tree/master/packages/path_provider
version: 0.4.1
version: 0.4.2

flutter:
plugin:
Expand Down