react-native-image-picker: open failed: EACCES (Permission denied) on Android 29 every time (I am certain it's setup properly) - works in Android 28

Environment info

System:
    OS: Linux 4.15 Ubuntu 18.04.3 LTS (Bionic Beaver)
    CPU: (8) x64 Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
    Memory: 2.16 GB / 61.90 GB
    Shell: 5.4.2 - /bin/zsh
  Binaries:
    Node: 13.2.0 - ~/.nvm/versions/node/v13.2.0/bin/node
    Yarn: 1.19.1 - /usr/bin/yarn
    npm: 6.13.1 - ~/.nvm/versions/node/v13.2.0/bin/npm
  SDKs:
    Android SDK:
      API Levels: 23, 26, 28, 29
      Build Tools: 23.0.1, 25.0.0, 28.0.3, 29.0.0, 29.0.2
      System Images: android-28 | Google APIs Intel x86 Atom_64, android-29 | Intel x86 Atom, android-29 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom_64
  npmPackages:
    react: 16.9.0 => 16.9.0 
    react-native: 0.61.4 => 0.61.4

Library version: 1.1.0

Steps To Reproduce

ImagePicker.launchImageLibrary(
  {
    title: "Select QR Code",
    storageOptions: {
      skipBackup: true,
      path: "images",
    },
    mediaType: "photo",
  },
  response => {
    console.log("Response = ", response)
    if (response.didCancel) {
      console.log("User cancelled image picker")
    } else if (response.error) {
      console.log("ImagePicker Error: ", response.error)
      Alert.alert("Error", response.error)
    } else {
      // process image here
    }
  },
)

The system permission dialogue is prompted and accepted. The proper permissions are without certain given. The app has the following in AndroidManifest:

  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.VIBRATE" />
  <uses-permission android:name="android.permission.READ_CONTACTS" />

But despite this the library returns a permission denied error every time like this:

/storage/emulated/0/DCIM/Camera/IMG_20191125_203629.jpg: open failed: EACCES (Permission denied)

Note: everything works as expected in the simulator but the permission error happens on a real device.

The simulator is running Android 28 and device is running Android 29 - is this an issue in the latest Android API version?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 29
  • Comments: 16

Most upvoted comments

Seems this is due to a change in Android 29 - found some more info in this stackoverflow post:

Starting with Android 11 the storage permission is getting revoked and developers would need to consider alternative ways of accessing the storage they need either through SAF or Media Store. For the time being, you can carry on using what you’re using by adding the following in your manifest within the application tags:

android:requestLegacyExternalStorage=“true” You might want to consider changing your minSDK to 19 and use getExternalFilesDir() to get a path that doesn’t require any permissions.

https://stackoverflow.com/questions/58430070/android-apiv29-filenotfoundexception-eacces-permission-denied

I was able to get react-native-image-picker working again by adding android:requestLegacyExternalStorage="true" to my <application ... > tag in AndroidManifest.xml.

But, this is only a temporary fix. I’m not experienced enough to submit a PR but hopefully this information helps someone who can upgrade the library for Android 29 and future releases.

see to here: https://developer.android.com/training/data-storage/use-cases

<manifest ... >
<!-- This attribute is "false" by default on apps targeting
     Android 10 or higher. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

@Jackyaung this is how it should be done

Screenshot from 2020-10-09 22-02-27

Screenshot from 2020-10-09 22-03-11

* Note that this is a temporary solution. In SDK 30 or newer it won’t work.

android diff

android:requestLegacyExternalStorage=“true”

doesn’t work for me anyone with an alternative

Just in case someone follows @sayem314 comment and run into

AAPT: error: attribute android:requestLegacyExternalStorage not found

In app/build.gradle

find subprojects and change it to

subprojects {
    afterEvaluate {project ->
        if (project.hasProperty("android")) {
            android {
                compileSdkVersion 29
                buildToolsVersion '29.0.3'
            }
        }
    }
}

android:requestLegacyExternalStorage=“true”

doesn’t work for me anyone with an alternative

@Michael-kyalo check what @HauLuu suggested https://github.com/react-native-image-picker/react-native-image-picker/issues/1233#issuecomment-711135457

It worked for me.