expo: [expo-media-library] get/request permission always returns undetermined / denied

Summary

MediaLibrary.getPermissionsAsync() always returns status:undetermined when granted(denied when denied), and when canAskAgain:true, requestPermissionsAsync() always returns granted:false immediately without asking.

Managed or bare workflow? If you have ios/ or android/ directories in your project, the answer is bare!

bare

What platform(s) does this occur on?

Android

SDK Version (managed workflow only)

43.0.3

Environment

Expo CLI 4.13.0 environment info: System: OS: macOS 11.6 Shell: 5.8 - /bin/zsh Binaries: Node: 12.19.0 - /usr/local/bin/node Yarn: 2.4.2 - /usr/local/bin/yarn npm: 8.1.3 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman Managers: CocoaPods: 1.11.2 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: iOS 15.0, DriverKit 20.4, macOS 11.3, tvOS 15.0, watchOS 8.0 IDEs: Android Studio: 4.1 AI-201.8743.12.41.6858069 Xcode: 13.0/13A233 - /usr/bin/xcodebuild npmPackages: expo: ^43.0.3 => 43.0.3 react: 17.0.1 => 17.0.1 react-dom: 17.0.1 => 17.0.1 react-native: 0.64.3 => 0.64.3 react-native-web: 0.17.1 => 0.17.1 npmGlobalPackages: expo-cli: 4.13.0 Expo Workflow: bare

Reproducible demo or steps to reproduce from a blank project

install bare workflow project, add dependencies expo 43.0.3, expo-media-library

let permission = await MediaLibrary.getPermissionsAsync(); if (!permission.granted) { if (permission.canAskAgain || permission.status === “undetermined”) { permission = await MediaLibrary.requestPermissionsAsync(false); if (!permission.granted) { //denied return; } } else { //denied return; } }

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 2
  • Comments: 44 (6 by maintainers)

Most upvoted comments

@emmbyiringiro thanks for your comment. But it doesn’t work as we want, unfortunately. EVEN THOUGH access is allowed in android settings, the return value for the function getPermissionAsync is

{granted:false, canAskAgain:false, status:"undetermined"}

when I expect as follows : {granted:true, canAskAgain:false, status:"granted"}

This happens when the user is denied permission and set to never ask again. Next time you tried to ask permission it resolve into denied.

You can handle this situation like this

const permission = await MediaLibrary.getPermissionsAsync();

// Detect if you can request this permission again

if (!permission.canAskAgain || permission.status === "denied") {
  /**
   *   Code to open device setting then the user can manually grant the app
   *  that permission
   */

  Linking.openSettings();
} else {
  if (permission.status === "granted") {
    // Your actually code require this permission
  }
}

PermissionResponse Type Definition

Same issue. my project ejected. Add <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" /> to src/main/AndroidManifest.xml, then it behaved as expected

To conclude possible problems and solutions:

  • If the permission is denied in Expo Go or it crashes, the fix will be published in SDK 45 (see my comments above). If it happens in apps built with expo build, the best workaround would be to use EAS Build.
  • If it happens in EAS Build or when using expo prebuild / expo run:android (the prebuild/config plugins workflow), make sure you’ve followed this configuration instruction - especially the isAccessMediaLocationEnabled property.
  • In ejected/bare workflow, apply the answer above about adding <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" /> to AndroidManifest.xml. Edit: The installation instruction for bare workflow is now updated.

I think the problem is that the ACCESS_MEDIA_LOCATION is required even if the app doesn’t need the photo location info.

I’ll keep this open for a while until it’s tracked internally or finally fixed.

I had the same issue, solved it after updating to expo 48. It was a problem of compatibilities between packages.

The root issue cause should be fixed now, it will be published with new version (> 14.0.0) of the expo-media-library package (along with SDK 45, but it might be sooner).

When the fix is published, adding ACCESS_MEDIA_LOCATION to AndroidManifest.xml or setting isAccessMediaLocationEnabled in config plugin will not be necessary unless you’re accessing location.latitude / location.latitude properties returned by getAssetInfoAsync().

Edit: In 14.0.1 my fix is still not published 🤦 - see changelog for sdk-44 branch

people actually stop using my npm package because of this issue , please this is urgent issue peoples cant upload images in their apps that already published… they said the same happen on a a Final Build too and not just the expo go …

@barthap do u know when expo release new version that includes your fix ?

issue is that 👍🏻

when u first enter and Allow permissions = ALL GOOD you can also deny them and re allow them all will work

when u first enter and Decline permissions = ALL BAD from now on

getPermissionsAsync() => result denied also if u restart the app and of course make settings permissions allowed

requestPermissionsAsync() => return [Unhandled promise rejection: Error: Encountered an exception while calling native method: Exception occurred while executing exported method requestPermissionsAsync on module ExponentMediaLibrary: String resource ID #0xffffffff]

thats not good , sometimes users Decline permissions by mistake , when we show them button that leads to Settings and they allow it manually , and return the app , (using appState to knows when)

at this point we must get the permissions (updated onces!)

it does work with instagram as i just tested. on expo with android and ios emulators it doesnt work.

same for me starting from expo 43

@endruuu thank you for reaching out, tried both separately and together, no success, all permissions are given in settings but MediaLibrary.getPermissionsAsync always respond with granted: false

nothing to sorry about , you help a lot and this is much appreciated ! Happy Holidays ! 👍🏻

Hello, sorry for late reply, I am on holiday. I believe my fix is only related to Expo Go so it happens in development only. If I’m wrong and you say it happens in standalone (built with expo build) apps too, try using EAS Build to build a new version of the app - this will omit the whole buggy Expo Go code.

I don’t know if it will be published before SDK 45 and I cannot promise that, I am not allowed to publish new versions of Expo Go, sorry

any idea when this fix will arrive ? is it suppose to be in next sdk 44.0.4 ?

Something I noticed in the docs for MediaLibrary: https://docs.expo.dev/versions/latest/sdk/media-library/#medialibraryrequestpermissionsasyncwriteonly

It says that it returns a PermissionsResponse object, which is stated to be an extension of EXPermissionsResponse.

To me it looks like the status may be “undetermined” because there is now more information provided in the PermissionsResponse object under the optional accessPrivileges key which can have values “all”, “limited” or “none”.

I am unable to reproduce this in Expo as the status is coming back as “granted”, but I’m running a new build for the Android store that has more exposure to what is being returned and I can update when that goes out, but I would guess that the root cause of the issue is that the response looks like:

{
  granted: false,
  canAskAgain: false,
  status: 'undetermined',
  accessPrivileges: 'all'
}

Edit: I exposed more information in my Android store build and it looks like accessPrivileges was undefined, so I don’t think this is the case.

hi still the bug in expo 50 ! solution :

useEffect(() => {
    console.log("permission camera :", permission);
    if (permission && !permission.granted) {
      Camera.requestCameraPermissionsAsync();
    }
  }, [permission]);

I seem to have a similar issue. Asking for camera permissions works fine for me but asking for image media library permissions always returns (even if I tinker with my app permission through the Android OS settings menu),

{ "canAskAgain": false, "expires": "never", "granted": false, "status": "denied", }

and I never get any prompt. I’ve skimmed over the documentation and noticed that for some reason it may not be necessary to ask for permissions to launch the image library? If this is true, why is there still code that handles media library permissions? What am I missing?

Any help is greatly appreciated. @barthap

@professorkolik how about this, at the last item? https://github.com/expo/expo/issues/15273#issuecomment-1005440392

It works on my bare workflow. Perhaps you encountered the same issue as mine? https://github.com/expo/expo/issues/15273#issuecomment-1034205379

This package is not usable anymore in bare workflow, any hotfix we can do to make it work?

My post you quoted applies to bare workflow.

For standalone apps built with legacy expo build, the fix will be applied with SDK 45, because it requires extra effort to apply changes there. The workaround for now is to use EAS Build.

@barthap I have a bare workflow and I confirm the add of ACCESS_MEDIA_LOCATION permission in Android Manifest fix the issue. I will test on various Android version today and I will keep you in touch.

Same issue. my project ejected. Add <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" /> to src/main/AndroidManifest.xml, then it behaved as expected

Thank you so much @zhujingfa , you made my day!

We’ve been investigating this issue now, a bunch of updates:

  • We’ve been able to reproduce it, but yet in Expo Go (managed workflow).
  • As far as we found out, there’s an issue in Expo Go, but should not happen on Android 9 and older. Affected SDKs are 43 and 44.
  • The reason is that in Expo Go, each app you develop can have a separate set of permissions and there is a bug in code handling them - this screen is missing (where “Expo APIs” is your app name): Screenshot 2021-12-20 at 12 36 50

We’re not sure about the root cause, but it definitely solved the Unhandled promise ... String resource ID #0xffffffff and most likely solved the issue from the @natysoz video (no longer able to reproduce).

same for me starting from expo 43