react-native: PermissionsAndroid.request never resolves

Is this a bug report?

Yes

Have you read the Contributing Guidelines?

Yes.

Environment

Environment: OS: macOS Sierra 10.12.6 Node: 9.4.0 Yarn: 1.3.2 npm: 5.6.0 Watchman: 4.9.0 Xcode: Xcode 9.2 Build version 9C40b Android Studio: 3.0 AI-171.4443003

Packages: (wanted => installed) react: 16.2.0 => 16.2.0 react-native: 0.53.0 => 0.53.0

Edit: according to @MateRyze, it still happens on react-native 0.55.4.

Target Platform: Android 6.0.1

Steps to Reproduce

We have a Camera component and it should check for the Camera permission before mounting.

In my app’s AndroidManifest.xml I have the line, along with many other permissions:

<uses-permission android:name="android.permission.CAMERA"/>

In our component’s componentDidMount() we call a function that should return true if we have permission and false if we do not have, here is the relevant snippet of the function:

if (Platform.OS === 'android') {
const isGranted = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.CAMERA);
      if (isGranted) {
        return true;
      }
      try {
        console.log('before request');
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.CAMERA,
          {
            title: 'Dialog Title',
            message: 'Dialog Message',
          }
        );
        console.log('after request');
        return granted === PermissionsAndroid.RESULTS.GRANTED;
      } catch (err) {
        console.log('error');
        console.log(err);
      }
}

Expected Behavior

A dialog with my title and message should appear, if the user clicks on “Allow”, the promise should resolve and my component should render as expected.

Actual Behavior

A dialog with a different message and title appears. I click on “Allow” and the promise is never resolved or rejected.

In my logs, only the “before request” log appears. Neitherconsole.log('after request') or console.log('error') is logged, so I presume the code is stuck in the await.

I am following this doc.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 14
  • Comments: 40 (1 by maintainers)

Most upvoted comments

Thanks for posting this! It looks like your issue may refer to an older version of React Native. Can you reproduce the issue on the latest release, v0.55?

Thank you for your contributions.

After debugging and trying a few cases. If the request is called with the rationale parameter as undefined the request permission works correctly. When the rationale object is provided permissions are not requested.

I’m using:

"react": "16.8.3",
"react-native": "0.59.9",

Relevant snippet:

  const askCameraPermission = async () => {
    try {
      const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA);
      console.log(granted)
    } catch {
      (e) => console.log(e)
    };
  };

App info’s permissions after -> before running method

pending -> granted BUT promise is not resolved, console.log doesn’t show. 👎 granted -> don't ask for permission because is already granted AND promise is resolved, console.log show ‘granted’ 👍

Up again. This error happens in one of our apps in production, we tried to make a workaround for it multiple times but nothing works. Even if we ask for the permission when the app starts, it still hangs and never resolves.

@aryo, will try to confirm what you said, thanks

Would love any follow up

I have upgraded my project from 0.57 to 0.61 . But the issue still exists. However if I try to create a new project with react-native 0.61 this issue is not there. I am stuck here. Please some one help me

Maybe you Override onRequestPermissionsResult in MainActivity extends ReactActivity but forget to call super.onRequestPermissionsResult.

I just wrapped it in another promise, seems to work well for me.

getPermissions() {
  return new Promise(async(resolve, reject) => {
    const permissions = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE);
    if (permissions === PermissionsAndroid.RESULTS.GRANTED) resolve(true);
    else reject(false);
  });
}

Hello there 👋 this issue has been reported for an old version of React Native. Ideally we’d like everyone to be using 0.59 (see the awesome changes it brought) but we know updating can be a pain. We are going to close this issue because it’s from a version before 0.57, which is really old.

But please, if it’s actually still an issue with 0.59 please comment below and we can reopen it 😊

@MateRyze before you installed:

"react": "16.4.0",
"react-native": "0.55.4",

did you also do a rm -rf ./node_modules package-lock.json?

The only difference might be that I’m using the “promise/then” syntax in lieu of “async/await”, ex:

    requestAndroidPermissions() {
        if (Platform.OS === 'android') {
            var permissions = [
                PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
                PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION
            ];

            try {
                PermissionsAndroid.requestMultiple(permissions).then(granted => {
                    // Object.entries(granted).map(([key, value]) => {
                    // });
                    this.nextAction();
                });
            } catch (err) {
                console.warn(err);
            }
        } else if (Platform.OS === 'ios') {
            this.nextAction();
        }
    }

which shouldn’t matter, but perhaps it does.

Updated to RN 0.55 and I have no more issues with PermissionsAndroid

Happening on RN 0.58.3.

Here’s perfectly working example for fresh 0.57 and Android 27 on physical phone:

class App extends Component {
  _requestPermissions = async () => {
    if (Platform.OS === 'android') { 
      const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA)
      return result === PermissionsAndroid.RESULTS.GRANTED || result === true
    }
    return true
  }

  componentDidMount = () => {
    async ({ _, status }) => {
      if (status !== 'PERMISSION_GRANTED') {
        await this._requestPermissions()
      }
    }
  }

  render() {
    return (
      <View style={styles.container}>
        <RNCamera style={styles.preview} type={RNCamera.Constants.Type.back} />
      </View>
    )
  }
}

So, basically an error is rather how and what permissions to ask, not React Native related. For example, if we would have used if (status !== 'PENDING_AUTHORIZATION') {, then the app will pop-up only on second run and first run will be promise rejected.

We fixed it by requesting the permission on app startup.

Using following versions: “react”: “16.4.0”, “react-native”: “0.55.4”, No other modules installed.

Problem: no dialog and the request doesn’t resolve. 😦 I am using the code from https://facebook.github.io/react-native/docs/permissionsandroid.htm

async function requestLocationPermission() {
  try {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      {
        'title': 'Cool Photo App Camera Permission',
        'message': 'Cool Photo App needs access to your camera ' +
          'so you can take awesome pictures.'
      }
    )
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      console.log("You can use the location service")
    } else {
      console.log("Location permission denied")
    }
  } catch (err) {
    console.warn(err)
  }
}

This is happening to us, appears to most reliably happen on one of our testers’ Nexus 6; doesn’t repro on some other Android devices. For us no matter if the permission is granted or denied, it can lead to the unresolving promise it seems. react-native-cli: 2.0.1 react-native: 0.51.0 platform: android builds: at least release builds