Search code examples
androidreact-nativelocationandroid-permissions

Checking for permissions always returns "denied". React Native


During the debugging process of React Native application on a physical device (Android) when I check for the location permission it's always blocked, even though I granted the permission in the settings. I have to note that I haven't been able to request the "ask for permission" window previously, so I couldn't block it in any way. Also, I tried to delete and let the app to be installed again.

Here's the code where I check for location permission (I tried others too). There I use react-native-permissions however, the behaviour is the same if I use PermissionsAndroid from react-native.

import {check, PERMISSIONS, request, RESULTS, openSettings} from "react-native-permissions";

async function checkPermissions() {
    let response = await check(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION); // <-- always blocked
    let isPermissionsGranted = false;

    if (response === RESULTS.GRANTED) {
        isPermissionsGranted = true;
    } else if (response === RESULTS.DENIED) {
        response = request(PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION, {
            title: "FreeLine requires permission",
            message: "FreeLine needs access to your location so you can see your position",
            buttonPositive: "Ok",
            buttonNegative: "Don't show my position",
        });

        if (response === RESULTS.GRANTED) {
            isPermissionsGranted = true;
        } else if (response === RESULTS.DENIED) {
            await openSettings();
        }
    }

    return isPermissionsGranted;
}

I haven't found any information that'd explain that. I thought that it's possible that during debugging I can't request for permission.


Solution

  • In the end, I found the root of the problem. The funniest thing it isn't connected with my code in any way. The problem was caused by the manifest, to be more precise by rules I included.

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
    <uses-feature android:name="android.permission.BLUETOOTH" android:required="true"/>
    <!-- Only foreground ble access -->
    <uses-feature android:name="android.permission.ACCESS_FINE_LOCATION" android:required="true"/>
    

    As you can see from the snippet above, I used use-feature. Here what the docs say about it:

    Google Play uses the elements declared in your app manifest to filter your app from devices that do not meet its hardware and software feature requirements.

    In addition to the rules above, I have to add uses-permission, like that:

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