Describe the bug
I use file picker in the demo application that creates automatically with Android Studio.
List<File> files = await FilePicker.getMultiFile();
print(files[0].readAsBytesSync());
after running this code with click event, app request permission of storage and after allowing it, showing screen of file picker without any error. after selecting one image and return to the app, in readAsBytesSync() function get this error:
Error Log
I/FilePickerDelegate(28458): [SingleFilePick] File URI:content://com.android.providers.media.documents/document/image%3A68742
E/FilePickerUtils(28458): Getting for API 19 or abovecontent://com.android.providers.media.documents/document/image%3A68742
E/FilePickerUtils(28458): Document URI
E/FilePickerUtils(28458): Media Document URI
I/FilePickerUtils(28458): Image Media Document URI
I/FilePickerDelegate(28458): Absolute file path:/storage/emulated/0/DCIM/Screenshots/Screenshot_2020-07-27-00-29-52-845_ir.tenian.office.jpg
E/flutter (28458): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: FileSystemException: Cannot open file, path = '/storage/emulated/0/DCIM/Screenshots/Screenshot_2020-07-27-00-29-52-845_ir.tenian.office.jpg' (OS Error: Permission denied, errno = 13)
E/flutter (28458): #0 _File.throwIfError (dart:io/file_impl.dart:645:7)
E/flutter (28458): #1 _File.openSync (dart:io/file_impl.dart:489:5)
E/flutter (28458): #2 _File.readAsBytesSync (dart:io/file_impl.dart:549:18)
E/flutter (28458): #3 _MyHomePageState.getFile (package:flutter_file_picker_test/main.dart:74:20)
E/flutter (28458): <asynchronous suspension>
After search and try and fail I found the issue that the target and build SDK is 29. After change it to 28, it works well!
Also it not working with SDK 30.
I think there is a problem with getting storage permission process in your plugin. I create demo of reproducing this error here:
https://github.com/bkhezry/flutter-file-picker-demo
Issue details
Flutter Version details
[✓] Flutter (Channel stable, v1.17.5, on Linux, locale en_US.UTF-8)
• Flutter version 1.17.5 at /home/bkhezry/flutter
• Framework revision 8af6b2f038 (4 weeks ago), 2020-06-30 12:53:55 -0700
• Engine revision ee76268252
• Dart version 2.8.4
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
• Android SDK at /home/bkhezry/Android/Sdk
• Platform android-30, build-tools 30.0.1
• Java binary at: /home/bkhezry/android-studio/jre/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.
[✓] Android Studio (version 4.0)
• Android Studio at /home/bkhezry/android-studio
• Flutter plugin version 48.0.2-dev.4
• Dart plugin version 193.7361
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
[✓] VS Code (version 1.47.2)
• VS Code at /usr/share/code
• Flutter extension version 3.12.2
[✓] Connected device (1 available)
• Redmi Note 7 • 1762cc53 • android-arm64 • Android 10 (API 29)
• No issues found!
@bkhezry with SDK 29 you need the requestLegacyStorage = true flag on your Manifest file. Do you have it?
@miguelpruivo with adding requestLegacyStorage = true the error didn't solve. Please check the demo app.
@bkhezry mine is working properly with the Demo app. Does that happen with simulator?
You may want to add the READ_PERMISSION flag on your manifest, but it shouldn't be required. Could you please try and let me know if it worked for you?
@marchellodev no. I run the app on Android devices. Xiaomi Redmi Note 7 with android 10.
No. I add
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
and android:requestLegacyExternalStorage="true" to android manifest and error not fix. I push the update to repo
Update:
We also test app in Genymotion Pixel 2 API 29 and got exactly same error.
@bkhezry I would like to help you out on this, but this looks like you are trying to access a directory which you don't have permission to read (oddly). If this was a plugin permission issue, would affect a lot of other users (to not say all).
Could you try picking from other directory? From which are you actually trying to pick?
@marchellodev I choose recently, Downloads and Instagram folder in my device, and all of them return this error.
I just change target SDK to 28 and error fix! I think maybe other developers use the third plugin for get permission for storage. I don't know. did you test it with Pixel 2 API 29?
@bkhezry ok, so I was able to replicate the issue with your sample (you can already delete it if you want) and was able to find a fix.
So it seems that lately there have been a lot of users complaining with this issue online (for reading/writing files in general with Flutter) and you are probably aware of that, a quick search will result in a bunch of results over GitHub and SO. It should work as it is, but, for some reason, if you have the optional targetSdkVersion 29 set on your app/build.gradle it will result in this error, whereas on the other hand, if you remove it, it will work perfectly. You should leave the android:requestLegacyExternalStorage="true" and the compileSdk 29. Only remove the targetSdkVersion which is optional anyway.
What could be causing this? I actually don't know, but neither seem the community online so far. Might be an issue related to the way Flutter SDK is handling the I/O operations that could be conflicting with it somehow.
Let me know if it worked for you.
Thank you!
@miguelpruivo Thank you for your time and quick response. Yes, with removing targetSdkVersion from Gradle, the error fixed.
I will be filled an issue in flutter repo also.
One more thing. I use image_picker https://pub.dev/packages/image_picker in one of my project with your file_picker. image_picker get storage permission from the user before file_picker and project with targetSdkVersion 29 work fine! maybe it can help to find out the problem or maybe it is flutter core problem with IO.
Thanks again :-)
@bkhezry that's because image_picker always create a new file even if you pick it from gallery — it creates a copy and then you actually pick the copy, that’s why you don’t have permission issues.
One of the main reasons why some people liked file_picker was also due the fact that I've always tried to prioritize picking the original file when possible and only creating a cached copy if it couldn't be resolved otherwise. But it's been hard to keep it that way and since iOS always creates a copy as well, #234 purposes exactly this, a reliable way to access files through its URI or a cached file with a path.
@bkhezry ok, so I was able to replicate the issue with your sample (you can already delete it if you want) and was able to find a fix.
So it seems that lately there have been a lot of users complaining with this issue online (for reading/writing files in general with Flutter) and you are probably aware of that, a quick search will result in a bunch of results over GitHub and SO. It should work as it is, but, for some reason, if you have the optional
targetSdkVersion 29set on yourapp/build.gradleit will result in this error, whereas on the other hand, if you remove it, it will work perfectly. You should leave theandroid:requestLegacyExternalStorage="true"and thecompileSdk 29. Only remove thetargetSdkVersionwhich is optional anyway.What could be causing this? I actually don't know, but neither seem the community online so far. Might be an issue related to the way Flutter SDK is handling the I/O operations that could be conflicting with it somehow.
Let me know if it worked for you.
Thank you!
Wasted a ton of time. I found your fix by a MIRACLE.
@Gyoko it may be a good idea to also add it to troubleshooting area on the wiki. 👀
Most helpful comment
@bkhezry ok, so I was able to replicate the issue with your sample (you can already delete it if you want) and was able to find a fix.
So it seems that lately there have been a lot of users complaining with this issue online (for reading/writing files in general with Flutter) and you are probably aware of that, a quick search will result in a bunch of results over GitHub and SO. It should work as it is, but, for some reason, if you have the optional
targetSdkVersion 29set on yourapp/build.gradleit will result in this error, whereas on the other hand, if you remove it, it will work perfectly. You should leave theandroid:requestLegacyExternalStorage="true"and thecompileSdk 29. Only remove thetargetSdkVersionwhich is optional anyway.What could be causing this? I actually don't know, but neither seem the community online so far. Might be an issue related to the way Flutter SDK is handling the I/O operations that could be conflicting with it somehow.
Let me know if it worked for you.
Thank you!