diff --git a/CHANGELOG.md b/CHANGELOG.md index 89969496..347df77c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.4 +##### Android +- Addresses an issue where an invalid custom file extension wouldn't throw an error when it should. Thank you @Jahn08. +- Fixes `getDirectoryPath()` [#745](https://github.com/miguelpruivo/flutter_file_picker/issues/745). Thank you @tomm1e. ## 3.0.3 #### Web diff --git a/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java b/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java index f25eff00..585b2459 100644 --- a/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java +++ b/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java @@ -165,7 +165,7 @@ public void onMethodCall(final MethodCall call, final MethodChannel.Result rawRe allowedExtensions = FileUtils.getMimeTypes((ArrayList) arguments.get("allowedExtensions")); } - if (fileType == "custom" && (allowedExtensions == null || allowedExtensions.length == 0)) { + if (call.method != null && call.method.equals("custom") && (allowedExtensions == null || allowedExtensions.length == 0)) { result.error(TAG, "Unsupported filter. Make sure that you are only using the extension without the dot, (ie., jpg instead of .jpg). This could also have happened because you are using an unsupported file extension. If the problem persists, you may want to consider using FileType.all instead.", null); } else { this.delegate.startFileExplorer(fileType, isMultipleSelection, withData, allowedExtensions, result); diff --git a/android/src/main/java/com/mr/flutter/plugin/filepicker/FileUtils.java b/android/src/main/java/com/mr/flutter/plugin/filepicker/FileUtils.java index fb03d061..d6f5b1e4 100644 --- a/android/src/main/java/com/mr/flutter/plugin/filepicker/FileUtils.java +++ b/android/src/main/java/com/mr/flutter/plugin/filepicker/FileUtils.java @@ -6,6 +6,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build; +import android.os.Environment; import android.os.storage.StorageManager; import android.provider.DocumentsContract; import android.provider.OpenableColumns; @@ -176,11 +177,29 @@ public static FileInfo openFileStream(final Context context, final Uri uri, bool } @Nullable + @SuppressWarnings("deprecation") public static String getFullPathFromTreeUri(@Nullable final Uri treeUri, Context con) { if (treeUri == null) { return null; } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + if (isDownloadsDocument(treeUri)) { + String docId = DocumentsContract.getDocumentId(treeUri); + String extPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); + if (docId.equals("downloads")) { + return extPath; + } else if (docId.matches("^ms[df]\\:.*")) { + String fileName = getFileName(treeUri, con); + return extPath + "/" + fileName; + } else if (docId.startsWith("raw:")) { + String rawPath = docId.split(":")[1]; + return rawPath; + } + return null; + } + } + String volumePath = getVolumePath(getVolumeIdFromTreeUri(treeUri), con); FileInfo.Builder fileInfo = new FileInfo.Builder(); @@ -208,6 +227,24 @@ public static String getFullPathFromTreeUri(@Nullable final Uri treeUri, Context } } + @Nullable + private static String getDirectoryPath(Class storageVolumeClazz, Object storageVolumeElement) { + try { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + Method getPath = storageVolumeClazz.getMethod("getPath"); + return (String) getPath.invoke(storageVolumeElement); + } + + Method getDirectory = storageVolumeClazz.getMethod("getDirectory"); + File f = (File) getDirectory.invoke(storageVolumeElement); + if (f != null) + return f.getPath(); + + } catch (Exception ex) { + return null; + } + return null; + } @SuppressLint("ObsoleteSdkInt") private static String getVolumePath(final String volumeId, Context context) { @@ -218,9 +255,10 @@ private static String getVolumePath(final String volumeId, Context context) { Class storageVolumeClazz = Class.forName("android.os.storage.StorageVolume"); Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList"); Method getUuid = storageVolumeClazz.getMethod("getUuid"); - Method getPath = storageVolumeClazz.getMethod("getPath"); Method isPrimary = storageVolumeClazz.getMethod("isPrimary"); Object result = getVolumeList.invoke(mStorageManager); + if (result == null) + return null; final int length = Array.getLength(result); for (int i = 0; i < length; i++) { @@ -229,12 +267,14 @@ private static String getVolumePath(final String volumeId, Context context) { Boolean primary = (Boolean) isPrimary.invoke(storageVolumeElement); // primary volume? - if (primary && PRIMARY_VOLUME_NAME.equals(volumeId)) - return (String) getPath.invoke(storageVolumeElement); + if (primary != null && PRIMARY_VOLUME_NAME.equals(volumeId)) { + return getDirectoryPath(storageVolumeClazz, storageVolumeElement); + } // other volumes? - if (uuid != null && uuid.equals(volumeId)) - return (String) getPath.invoke(storageVolumeElement); + if (uuid != null && uuid.equals(volumeId)) { + return getDirectoryPath(storageVolumeClazz, storageVolumeElement); + } } // not found. return null; @@ -243,6 +283,10 @@ private static String getVolumePath(final String volumeId, Context context) { } } + private static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static String getVolumeIdFromTreeUri(final Uri treeUri) { final String docId = DocumentsContract.getTreeDocumentId(treeUri); diff --git a/example/lib/main.dart b/example/lib/main.dart index 80b9afa3..9002aba0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,4 +1,4 @@ import 'package:file_picker_example/src/file_picker_demo.dart'; import 'package:flutter/widgets.dart'; -void main() => runApp(new FilePickerDemo()); +void main() => runApp(FilePickerDemo()); diff --git a/pubspec.yaml b/pubspec.yaml index 6f4a843d..df7bdbc5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: file_picker description: A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extension filtering support. homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker -version: 3.0.3 +version: 3.0.4 dependencies: flutter: