React-native-image-crop-picker: Permissions Broken For Android 29 (Q) on any openPicker/openCamera calls due to Environment API Deprecations

Created on 18 Sep 2019  路  7Comments  路  Source: ivpusic/react-native-image-crop-picker

Version

  • react-native-image-crop-picker v0.25.0
  • react-native v0.59.10

Platform

  • Android

Expected behaviour

On a device running Android SDK 29 a call to ImagePicker.openCamera/ImagePicker.openPicker should prompt for permissions and then on acceptance open the picker or camera

Actual behaviour

Even when the user grants permissions the picker or camera will eventually fail once an attempt is made to get a storage directory

Steps to reproduce

  1. Have Phone Running Android SDK 29

  2. Use openCamera or openPicker and grant required permissions

  3. openCamera fails immediately and openPicker fails at cropping phase

Attachments

For openCamera the following error appears with no stack trace:
E/image-crop-picker: Promise rejected. Permission denied

For openPicker there is a full stack trace

2019-09-18 17:39:08.417 19436-19436/com.flyclops.domino.android E/TransformImageView: onFailure: setImageUri
    java.io.FileNotFoundException: open failed: EACCES (Permission denied)
        at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:315)
        at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:220)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1498)
        at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:1338)
        at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:1286)
        at com.yalantis.ucrop.task.BitmapLoadTask.doInBackground(BitmapLoadTask.java:100)
        at com.yalantis.ucrop.task.BitmapLoadTask.doInBackground(BitmapLoadTask.java:44)
        at android.os.AsyncTask$3.call(AsyncTask.java:378)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
2019-09-18 17:39:08.467 19436-19436/com.flyclops.domino.android E/image-crop-picker: Promise rejected. Cannot find image data

I discovered the general Android 29 behavior here
https://stackoverflow.com/questions/8854359/exception-open-failed-eacces-permission-denied-on-android`

which led to a solution suggestion here
https://stackoverflow.com/questions/56468539/getexternalstoragepublicdirectory-deprecated-in-android-q

More info in deprecation here https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)

I am very willing to work on adding support, I'm reaching out mostly for guidance on the process for doing so.

Love react-native-image-crop-picker? Please consider supporting our collective:
馃憠 https://opencollective.com/react-native-image-crop-picker/donate

Most helpful comment

Possibly related (fixed permissions issues for me):

Per the second link:

To give users more control over their files and to limit file clutter, apps targeting Android 10 (API level 29) and higher are given scoped access into an external storage device, or scoped storage, by default. Such apps can see only their app-specific directory鈥攁ccessed using Context.getExternalFilesDir()鈥攁nd specific types of media.

Workaround:
<application android:requestLegacyExternalStorage="true" ... >

I believe the real solution would be to change the location where files are being stored to use Context.getExternalFilesDir(); this pull request might fix it:
https://github.com/ivpusic/react-native-image-crop-picker/pull/1127

All 7 comments

Can anybody give guidance on how to get the project set up for android development? If I just open the .iml I get issues with the library plugin not being found, and if I explicitly put in a gradle dependency it fails to find the react-native library. I'm definitely down to try and fix this for the community, I'm just struggling to get up to speed

um, the documentation says:

If you are using react-native >= 0.60 use react-native-image-crop-picker version >= 0.25.0. Otherwise use version < 0.25.0.

and your versions are:

react-native-image-crop-picker v0.25.0
react-native v0.59.10

I'm not sure whether this is the reason but who knows.

I've Jetified react native 59.10 for compatibility between the two. Everything works without a hitch using targetSdkVersion 28, but as soon as that is flipped to targetSdkVersion 29 the filesystem calls fail with perm problems due to how Android deprecated their Environment apis in a breaking way. At this point in React Native 61 the targetSdkVersion is still set to 28 so almost all users will not be affected yet, but this library is essentially a time bomb for the day that react native finally upgrades

Possibly related (fixed permissions issues for me):

Per the second link:

To give users more control over their files and to limit file clutter, apps targeting Android 10 (API level 29) and higher are given scoped access into an external storage device, or scoped storage, by default. Such apps can see only their app-specific directory鈥攁ccessed using Context.getExternalFilesDir()鈥攁nd specific types of media.

Workaround:
<application android:requestLegacyExternalStorage="true" ... >

I believe the real solution would be to change the location where files are being stored to use Context.getExternalFilesDir(); this pull request might fix it:
https://github.com/ivpusic/react-native-image-crop-picker/pull/1127

Thanks for the workaround! Worked like a charm!

Was this page helpful?
0 / 5 - 0 ratings