Permissions.getAsync(Permissions.CAMERA_ROLL) "status=denied" when granted

If a user denies permission to the camera roll, then enabled permissions in their settings, getAsync still responds with “denied.” Requesting permissions again does result in a prompt being displayed, but without ‘denied’ accurately reporting, its difficult to know when to send the user to app settings.

To summarize, to reproduce the problem:

  1. Click “Get Photo”
  2. Deny Permissions
  3. Go to Expo Settings enabled “Photo Settings”
  4. Reopen app, and click “Get Photo” - notice that getAsync still responds with “denied”

Hi @freakthemighty - this is due to a recent change we made to scope permissions by app in the expo client. I don’t think there’s a great way around this in the client app right now, since when a user “denies” permission the client has no idea if they intend to deny permission just to that app, or to the entire expo client. You may just need to err on the side of using askAsync more.

However, note that this should not be a problem in standalone apps (i.e. “denied” will reliably reflect the OS-level permission).

cc @aalices in case there’s something I missed here.

Thanks, that clears things up.

@esamelson I just built our app an tested on a simulator (exp build:ios -t simulator), but it appears I’m still getting ‘denied’, after granting permissions in app settings. Am I missing something, shouldn’t this work?

1 Like

Does it also return denied when you use askAsync ?

@aalices, no “denied” is coming from the getAsync status. To make maters worse/more confusing, we’re now seeing similar behavior where we didn’t see if before while using SDK 25. We’re now seeing the ‘denied’ state while querying the status of the locations permissions.

Along with that we started to see the Expo permissions dialog in our TestFlight build. The dialog says something like, “you’ve already granted this permission for other Expo experiences.” While we’re proud to use Expo, this is not the sort of message we want to have user facing.

@aalices apologies, I misread your question.

I’m not sure if its also denied for askAsync, I’ll have to try to confirm. Its a little difficult to debug this stuff because the remote builds take time and then, as near as I know I can’t attach to the simulator build to add break points or read log statements.

Okay, so if you’re using SDK 25 try following this post:

This should show a proper modal on Expo client. For standalone we’re going to release a patch so your users won’t see the custom modal.

@aalices thanks so much for your quick replies. We’re giving this a try right now and will report back.

I’m trying to understand what changed though. Was this a regression? If so, how are we seeing it without changing our sdkVersion?

We have a production build deployed with 25.0.0 where we didn’t see this issue so I want to make sure I understand what gave rise to the problem we’re seeing.

This is due to the changes we made to handling the permissions and it was included in all Expo versions along with the newest release. That’s why you’re seeing it even if you did not upgrade. Sorry for the issues that appeared with this!

1 Like

To be clear, this would have only presented itself for new remote builds? It would not show up for currently deployed apps or for apps tested locally without doing npm install again?

@freakthemighty - it would only show up for new remote builds, or apps tested locally after updating the Expo client to 2.5.x. Previously deployed production apps would not have been affected.

1 Like

@aalices 25.0.1 does seem to have partially fixed the problem, but I still get that Expo permission modal. That modal is problematic for two reasons.

  1. Our users don’t know what Expo is. Messaging out users about something as sensitive as location permissions while mentioning a third unknown party will be confusing.
  2. I was able to click “Deny” on the Expo app even when the app settings were enabled.

Is there anyway we can rollback to the behavior we had before the update to 25? We’re trying to get a release out. After that we’ll have more time to dig into these issues.

Also, I’m curious to understand what the circumstance were that required the version 25.0.0 release to be updated in place.

We’re going to sign up for support to see if we can’t get unblocked for this.

Despite being locked at version 25, we’re seeing serious regressions with our permissions related code. I was working on updating 27 by asking for permissions before accessing the camera/gallery, but now we’re seeing that code that once worked for version 25, no longer works for 25.

@freakthemighty we solved the issue with the modal appearing on standalone apps, if you run exp build:ios one more time, the custom modal should no longer appear. It was intentionally designed to appear only when using Expo Client. Let us know if this works for your build

@aalices I confirmed that the modal fix works. The remaining issue is that the launchCameraAsync and launchImageLibraryAsync permission behaviors appear to have changed for 25.0.0. I’ve gotten some mixed signal from the Expo team regarding whether this was intentional and whether it was a bug and will be fixed.

From my perspective anything that changes the interface/behavior of an existing version or really any version that’s not a major release is a bug.

Having similar issue as well with returning new device settings changed.

const { status } = await Permissions.getAsync(Permissions.CAMERA);

The status is always denied. It works the first time but if going back to device settings and turning the switch off and then on again. getAsync always returns denied even if the device setting have the given permission.

Here is a snack to run on device Permissions with ImagePicker Mismatch with Device Settings - Snack

Okay,

Asking for permission again with askAsync does reset it within the app. Should’ve tried this before replying. It works now. Hope this helps someone :grinning:

1 Like

I tried using askAsync with no luck. This was working a few weeks ago. No code changes and suddenly it is broken. Can you take a look and advise please?

import { ImagePicker, Permissions } from 'expo';

    const permission = await Permissions.askAsync(Permissions.CAMERA_ROLL);
    if (permission.status !== 'granted') {
      // Permission was denied...
      return;
    }

    const result = await ImagePicker.launchImageLibraryAsync({
      allowsEditing: true,
      aspect: [3.5, 2],
      base64: true,
      mediaTypes: ImagePicker.MediaTypeOptions.Images
    });

I don’t get asked to give permission, only a yellow box error saying I don’t have camera roll permission.

For me, I’m only asking if Permissions.getAsync returns ‘denied’ or ‘undetermined’.

Then I check the result of askAsync

      await Permissions.askAsync(Permissions.CAMERA).then((data) => {
        if (data.status === DENIED) {
          return;
        }
      });