see changelog (1.3.7) (#102)
This commit is contained in:
parent
b72483dc66
commit
c8f5d4fe69
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,3 +1,15 @@
|
||||||
|
## 1.3.7
|
||||||
|
|
||||||
|
**Rollback - Breaking change:** Re-adds runtime verification for external storage read permission. Don't forget to add the permission to the `AndroidManifest.xml` file as well. More info in the README file.
|
||||||
|
**Bug fix:** Fixes a crash that could cause some Android API to crash when multiple files were selected from external storage.
|
||||||
|
|
||||||
|
## 1.3.6
|
||||||
|
|
||||||
|
**Improvements**
|
||||||
|
* Removes the Android write permissions requirement.
|
||||||
|
* Minor improvements in the example app.
|
||||||
|
* Now the exceptions are rethrown in case the user wants to handle them, despite that already being done in the plugin call.
|
||||||
|
|
||||||
## 1.3.5
|
## 1.3.5
|
||||||
|
|
||||||
**Bug fix:** Fixes an issue that could prevent users to pick files from the iCloud Drive app, on versions below iOS 11.
|
**Bug fix:** Fixes an issue that could prevent users to pick files from the iCloud Drive app, on versions below iOS 11.
|
||||||
|
|
13
README.md
13
README.md
|
@ -11,15 +11,16 @@ A package that allows you to use a native file explorer to pick single or multip
|
||||||
First, add *file_picker* as a dependency in [your pubspec.yaml file](https://flutter.io/platform-plugins/).
|
First, add *file_picker* as a dependency in [your pubspec.yaml file](https://flutter.io/platform-plugins/).
|
||||||
|
|
||||||
```
|
```
|
||||||
file_picker: ^1.3.5
|
file_picker: ^1.3.7
|
||||||
```
|
```
|
||||||
### Android
|
### Android
|
||||||
Add
|
|
||||||
|
Add
|
||||||
```
|
```
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
```
|
```
|
||||||
before `<application>` to your app's `AndroidManifest.xml` file. This is required due to file caching when a path is required from a remote file (eg. Google Drive).
|
before `<application>` to your app's `AndroidManifest.xml` file. This is required to access files from external storage.
|
||||||
|
|
||||||
|
|
||||||
### iOS
|
### iOS
|
||||||
Based on the location of the files that you are willing to pick paths, you may need to add some keys to your iOS app's _Info.plist_ file, located in `<project root>/ios/Runner/Info.plist`:
|
Based on the location of the files that you are willing to pick paths, you may need to add some keys to your iOS app's _Info.plist_ file, located in `<project root>/ios/Runner/Info.plist`:
|
||||||
|
@ -108,6 +109,8 @@ String someFilePath = filePaths['fileName']; // Access a file path directly by i
|
||||||
* [X] Load path from **any**
|
* [X] Load path from **any**
|
||||||
* [X] Create a `File` object from **any** selected file
|
* [X] Create a `File` object from **any** selected file
|
||||||
|
|
||||||
|
If you have any feature that you want to see in this package, please add it [here](https://github.com/miguelpruivo/plugins_flutter_file_picker/issues/99). 🎉
|
||||||
|
|
||||||
## Demo App
|
## Demo App
|
||||||
|
|
||||||
![Demo](https://github.com/miguelpruivo/plugins_flutter_file_picker/blob/master/example/example.gif)
|
![Demo](https://github.com/miguelpruivo/plugins_flutter_file_picker/blob/master/example/example.gif)
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class FilePickerPlugin implements MethodCallHandler {
|
||||||
private static final int REQUEST_CODE = (FilePickerPlugin.class.hashCode() + 43) & 0x0000ffff;
|
private static final int REQUEST_CODE = (FilePickerPlugin.class.hashCode() + 43) & 0x0000ffff;
|
||||||
private static final int PERM_CODE = (FilePickerPlugin.class.hashCode() + 50) & 0x0000ffff;
|
private static final int PERM_CODE = (FilePickerPlugin.class.hashCode() + 50) & 0x0000ffff;
|
||||||
private static final String TAG = "FilePicker";
|
private static final String TAG = "FilePicker";
|
||||||
private static final String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
private static final String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||||
|
|
||||||
private static Result result;
|
private static Result result;
|
||||||
private static Registrar instance;
|
private static Registrar instance;
|
||||||
|
@ -63,6 +63,9 @@ public class FilePickerPlugin implements MethodCallHandler {
|
||||||
while(currentItem < count) {
|
while(currentItem < count) {
|
||||||
final Uri currentUri = data.getClipData().getItemAt(currentItem).getUri();
|
final Uri currentUri = data.getClipData().getItemAt(currentItem).getUri();
|
||||||
String path = FileUtils.getPath(currentUri, instance.context());
|
String path = FileUtils.getPath(currentUri, instance.context());
|
||||||
|
if(path == null) {
|
||||||
|
path = FileUtils.getUriFromRemote(instance.activeContext(), currentUri, result);
|
||||||
|
}
|
||||||
paths.add(path);
|
paths.add(path);
|
||||||
Log.i(TAG, "[MultiFilePick] File #" + currentItem + " - URI: " +currentUri.getPath());
|
Log.i(TAG, "[MultiFilePick] File #" + currentItem + " - URI: " +currentUri.getPath());
|
||||||
currentItem++;
|
currentItem++;
|
||||||
|
@ -174,21 +177,26 @@ public class FilePickerPlugin implements MethodCallHandler {
|
||||||
Intent intent;
|
Intent intent;
|
||||||
|
|
||||||
if (checkPermission()) {
|
if (checkPermission()) {
|
||||||
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||||
intent = new Intent(Intent.ACTION_PICK);
|
intent = new Intent(Intent.ACTION_PICK);
|
||||||
} else {
|
} else {
|
||||||
intent = new Intent(Intent.ACTION_GET_CONTENT);
|
intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath() + File.separator);
|
Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath() + File.separator);
|
||||||
intent.setDataAndType(uri, type);
|
intent.setDataAndType(uri, type);
|
||||||
intent.setType(type);
|
intent.setType(type);
|
||||||
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, isMultipleSelection);
|
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, isMultipleSelection);
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
|
|
||||||
instance.activity().startActivityForResult(intent, REQUEST_CODE);
|
if (intent.resolveActivity(instance.activity().getPackageManager()) != null) {
|
||||||
|
instance.activity().startActivityForResult(intent, REQUEST_CODE);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Can't find a valid activity to handle the request. Make sure you've a file explorer installed.");
|
||||||
|
result.error(TAG, "Can't handle the provided file type.", null);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
requestPermission();
|
requestPermission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,6 @@ import java.io.InputStream;
|
||||||
|
|
||||||
import io.flutter.plugin.common.MethodChannel;
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
/**
|
|
||||||
* Credits to NiRRaNjAN from utils extracted of in.gauriinfotech.commons;.
|
|
||||||
**/
|
|
||||||
|
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
|
|
||||||
private static final String TAG = "FilePickerUtils";
|
private static final String TAG = "FilePickerUtils";
|
||||||
|
@ -109,9 +105,11 @@ public class FileUtils {
|
||||||
}
|
}
|
||||||
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
|
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
|
||||||
Log.e(TAG, "NO DOCUMENT URI - CONTENT");
|
Log.e(TAG, "NO DOCUMENT URI - CONTENT");
|
||||||
if (isGooglePhotosUri(uri))
|
if (isGooglePhotosUri(uri)) {
|
||||||
return uri.getLastPathSegment();
|
return uri.getLastPathSegment();
|
||||||
|
} else if (isDropBoxUri(uri)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return getDataColumn(context, uri, null, null);
|
return getDataColumn(context, uri, null, null);
|
||||||
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||||
Log.e(TAG, "No DOCUMENT URI - FILE");
|
Log.e(TAG, "No DOCUMENT URI - FILE");
|
||||||
|
@ -177,11 +175,12 @@ public class FileUtils {
|
||||||
|
|
||||||
public static String getUriFromRemote(Context context, Uri uri, MethodChannel.Result result) {
|
public static String getUriFromRemote(Context context, Uri uri, MethodChannel.Result result) {
|
||||||
|
|
||||||
|
Log.i(TAG, "Caching file from remote/external URI");
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
String cloudFile = context.getCacheDir().getAbsolutePath() + "/" + FileUtils.getFileName(uri, context);
|
String externalFile = context.getCacheDir().getAbsolutePath() + "/" + FileUtils.getFileName(uri, context);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fos = new FileOutputStream(cloudFile);
|
fos = new FileOutputStream(externalFile);
|
||||||
try {
|
try {
|
||||||
BufferedOutputStream out = new BufferedOutputStream(fos);
|
BufferedOutputStream out = new BufferedOutputStream(fos);
|
||||||
InputStream in = context.getContentResolver().openInputStream(uri);
|
InputStream in = context.getContentResolver().openInputStream(uri);
|
||||||
|
@ -208,10 +207,13 @@ public class FileUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "Remote file loaded and cached at:" + cloudFile);
|
Log.i(TAG, "File loaded and cached at:" + externalFile);
|
||||||
return cloudFile;
|
return externalFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isDropBoxUri(Uri uri) {
|
||||||
|
return "com.dropbox.android.FileCache".equals(uri.getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isExternalStorageDocument(Uri uri) {
|
private static boolean isExternalStorageDocument(Uri uri) {
|
||||||
return "com.android.externalstorage.documents".equals(uri.getAuthority());
|
return "com.android.externalstorage.documents".equals(uri.getAuthority());
|
||||||
|
|
|
@ -22,7 +22,6 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
|
||||||
applicationId "com.mr.flutter.plugin.filepickerexample"
|
applicationId "com.mr.flutter.plugin.filepickerexample"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
|
@ -33,7 +32,6 @@ android {
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
to allow setting breakpoints, to provide hot reload, etc.
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
-->
|
-->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
|
|
||||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||||
|
|
|
@ -31,10 +31,12 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
||||||
try {
|
try {
|
||||||
if (_multiPick) {
|
if (_multiPick) {
|
||||||
_path = null;
|
_path = null;
|
||||||
_paths = await FilePicker.getMultiFilePath(type: _pickingType, fileExtension: _extension);
|
_paths = await FilePicker.getMultiFilePath(
|
||||||
|
type: _pickingType, fileExtension: _extension);
|
||||||
} else {
|
} else {
|
||||||
_paths = null;
|
_paths = null;
|
||||||
_path = await FilePicker.getFilePath(type: _pickingType, fileExtension: _extension);
|
_path = await FilePicker.getFilePath(
|
||||||
|
type: _pickingType, fileExtension: _extension);
|
||||||
}
|
}
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
print("Unsupported operation" + e.toString());
|
print("Unsupported operation" + e.toString());
|
||||||
|
@ -42,7 +44,9 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_fileName = _path != null ? _path.split('/').last : _paths != null ? _paths.keys.toString() : '...';
|
_fileName = _path != null
|
||||||
|
? _path.split('/').last
|
||||||
|
: _paths != null ? _paths.keys.toString() : '...';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,14 +99,15 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
ConstrainedBox(
|
new ConstrainedBox(
|
||||||
constraints: BoxConstraints.tightFor(width: 100.0),
|
constraints: BoxConstraints.tightFor(width: 100.0),
|
||||||
child: _pickingType == FileType.CUSTOM
|
child: _pickingType == FileType.CUSTOM
|
||||||
? new TextFormField(
|
? new TextFormField(
|
||||||
maxLength: 15,
|
maxLength: 15,
|
||||||
autovalidate: true,
|
autovalidate: true,
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
decoration: InputDecoration(labelText: 'File extension'),
|
decoration:
|
||||||
|
InputDecoration(labelText: 'File extension'),
|
||||||
keyboardType: TextInputType.text,
|
keyboardType: TextInputType.text,
|
||||||
textCapitalization: TextCapitalization.none,
|
textCapitalization: TextCapitalization.none,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
|
@ -112,6 +117,7 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
||||||
return 'Invalid format';
|
return 'Invalid format';
|
||||||
}
|
}
|
||||||
_hasValidMime = true;
|
_hasValidMime = true;
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: new Container(),
|
: new Container(),
|
||||||
|
@ -119,8 +125,10 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
||||||
new ConstrainedBox(
|
new ConstrainedBox(
|
||||||
constraints: BoxConstraints.tightFor(width: 200.0),
|
constraints: BoxConstraints.tightFor(width: 200.0),
|
||||||
child: new SwitchListTile.adaptive(
|
child: new SwitchListTile.adaptive(
|
||||||
title: new Text('Pick multiple files', textAlign: TextAlign.right),
|
title: new Text('Pick multiple files',
|
||||||
onChanged: (bool value) => setState(() => _multiPick = value),
|
textAlign: TextAlign.right),
|
||||||
|
onChanged: (bool value) =>
|
||||||
|
setState(() => _multiPick = value),
|
||||||
value: _multiPick,
|
value: _multiPick,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -132,30 +140,40 @@ class _FilePickerDemoState extends State<FilePickerDemo> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
new Builder(
|
new Builder(
|
||||||
builder: (BuildContext context) => new Container(
|
builder: (BuildContext context) =>
|
||||||
padding: const EdgeInsets.only(bottom: 30.0),
|
_path != null || _paths != null
|
||||||
height: MediaQuery.of(context).size.height * 0.50,
|
? new Container(
|
||||||
child: new Scrollbar(
|
padding: const EdgeInsets.only(bottom: 30.0),
|
||||||
child: _path != null || _paths != null
|
height: MediaQuery.of(context).size.height * 0.50,
|
||||||
? new ListView.separated(
|
child: new Scrollbar(
|
||||||
itemCount: _paths != null && _paths.isNotEmpty ? _paths.length : 1,
|
child: new ListView.separated(
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemCount: _paths != null && _paths.isNotEmpty
|
||||||
final bool isMultiPath = _paths != null && _paths.isNotEmpty;
|
? _paths.length
|
||||||
final String name = 'File $index: ' + (isMultiPath ? _paths.keys.toList()[index] : _fileName ?? '...');
|
: 1,
|
||||||
final path = isMultiPath ? _paths.values.toList()[index].toString() : _path;
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final bool isMultiPath =
|
||||||
|
_paths != null && _paths.isNotEmpty;
|
||||||
|
final String name = 'File $index: ' +
|
||||||
|
(isMultiPath
|
||||||
|
? _paths.keys.toList()[index]
|
||||||
|
: _fileName ?? '...');
|
||||||
|
final path = isMultiPath
|
||||||
|
? _paths.values.toList()[index].toString()
|
||||||
|
: _path;
|
||||||
|
|
||||||
return new ListTile(
|
return new ListTile(
|
||||||
title: new Text(
|
title: new Text(
|
||||||
name,
|
name,
|
||||||
),
|
),
|
||||||
subtitle: new Text(path),
|
subtitle: new Text(path),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (BuildContext context, int index) => new Divider(),
|
separatorBuilder:
|
||||||
)
|
(BuildContext context, int index) =>
|
||||||
: new Container(),
|
new Divider(),
|
||||||
),
|
)),
|
||||||
),
|
)
|
||||||
|
: new Container(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="JAVA_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.idea" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/example/.pub" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/example/build" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
|
||||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
|
||||||
<orderEntry type="library" name="Flutter Plugins" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="JAVA_MODULE" version="4">
|
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="android" name="Android">
|
|
||||||
<configuration>
|
|
||||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
|
||||||
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/android/gen" />
|
|
||||||
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/android/gen" />
|
|
||||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/android/AndroidManifest.xml" />
|
|
||||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/android/res" />
|
|
||||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/android/assets" />
|
|
||||||
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/android/libs" />
|
|
||||||
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/android/proguard_logs" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$/android">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/android/src/main/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/android/gen" isTestSource="false" generated="true" />
|
|
||||||
</content>
|
|
||||||
<content url="file://$MODULE_DIR$/example/android">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/example/android/app/src/main/java" isTestSource="false" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="Flutter for Android" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
|
@ -23,7 +23,8 @@ class FilePicker {
|
||||||
/// A [fileExtension] can be provided to filter the picking results.
|
/// A [fileExtension] can be provided to filter the picking results.
|
||||||
/// If provided, it will be use the `FileType.CUSTOM` for that [fileExtension].
|
/// If provided, it will be use the `FileType.CUSTOM` for that [fileExtension].
|
||||||
/// If not, `FileType.ANY` will be used and any combination of files can be multi picked at once.
|
/// If not, `FileType.ANY` will be used and any combination of files can be multi picked at once.
|
||||||
static Future<Map<String, String>> getMultiFilePath({FileType type = FileType.ANY, String fileExtension}) async =>
|
static Future<Map<String, String>> getMultiFilePath(
|
||||||
|
{FileType type = FileType.ANY, String fileExtension}) async =>
|
||||||
await _getPath(_handleType(type, fileExtension), true);
|
await _getPath(_handleType(type, fileExtension), true);
|
||||||
|
|
||||||
/// Returns an absolute file path from the calling platform.
|
/// Returns an absolute file path from the calling platform.
|
||||||
|
@ -31,15 +32,18 @@ class FilePicker {
|
||||||
/// A [type] must be provided to filter the picking results.
|
/// A [type] must be provided to filter the picking results.
|
||||||
/// Can be used a custom file type with `FileType.CUSTOM`. A [fileExtension] must be provided (e.g. PDF, SVG, etc.)
|
/// Can be used a custom file type with `FileType.CUSTOM`. A [fileExtension] must be provided (e.g. PDF, SVG, etc.)
|
||||||
/// Defaults to `FileType.ANY` which will display all file types.
|
/// Defaults to `FileType.ANY` which will display all file types.
|
||||||
static Future<String> getFilePath({FileType type = FileType.ANY, String fileExtension}) async =>
|
static Future<String> getFilePath(
|
||||||
|
{FileType type = FileType.ANY, String fileExtension}) async =>
|
||||||
await _getPath(_handleType(type, fileExtension), false);
|
await _getPath(_handleType(type, fileExtension), false);
|
||||||
|
|
||||||
/// Returns a `File` object from the selected file path.
|
/// Returns a `File` object from the selected file path.
|
||||||
///
|
///
|
||||||
/// This is an utility method that does the same of `getFilePath()` but saving some boilerplate if
|
/// This is an utility method that does the same of `getFilePath()` but saving some boilerplate if
|
||||||
/// you are planing to create a `File` for the returned path.
|
/// you are planing to create a `File` for the returned path.
|
||||||
static Future<File> getFile({FileType type = FileType.ANY, String fileExtension}) async {
|
static Future<File> getFile(
|
||||||
final String filePath = await _getPath(_handleType(type, fileExtension), false);
|
{FileType type = FileType.ANY, String fileExtension}) async {
|
||||||
|
final String filePath =
|
||||||
|
await _getPath(_handleType(type, fileExtension), false);
|
||||||
return filePath != null ? File(filePath) : null;
|
return filePath != null ? File(filePath) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,15 +54,18 @@ class FilePicker {
|
||||||
if (result is String) {
|
if (result is String) {
|
||||||
result = [result];
|
result = [result];
|
||||||
}
|
}
|
||||||
return Map<String, String>.fromIterable(result, key: (path) => path.split('/').last, value: (path) => path);
|
return Map<String, String>.fromIterable(result,
|
||||||
|
key: (path) => path.split('/').last, value: (path) => path);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
print('[$_tag] Platform exception: ' + e.toString());
|
print('[$_tag] Platform exception: $e');
|
||||||
|
rethrow;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('[$_tag] Unsupported operation. Method not found. The exception thrown was: ' + e.toString());
|
print(
|
||||||
|
'[$_tag] Unsupported operation. Method not found. The exception thrown was: $e');
|
||||||
|
rethrow;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static String _handleType(FileType type, String fileExtension) {
|
static String _handleType(FileType type, String fileExtension) {
|
||||||
|
|
|
@ -2,7 +2,8 @@ name: file_picker
|
||||||
description: A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extensions filtering support.
|
description: A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extensions filtering support.
|
||||||
author: Miguel Ruivo <miguel@miguelruivo.com>
|
author: Miguel Ruivo <miguel@miguelruivo.com>
|
||||||
homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker
|
homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker
|
||||||
version: 1.3.5
|
version: 1.3.7
|
||||||
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
|
Loading…
Reference in New Issue