d3f4u1t3d
d3f4u1t3d

Reputation: 160

PermissionAndroid.request() always returns never_ask_again without any prompt. React Native

I already tried results from most of the questions but none worked for me. I try accessing the WRITE_EXTERNAL_STORAGE permission using the PermissionAndroid.request method but it always returns never_ask_again as the result.

My requestFile:

try {
        const granted = await PermissionsAndroid.request(
          PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
          {
            title: 'External Storage Write Permission',
            message: 'App needs write permission',
          },
        );

        console.log(granted);
        if (granted === PermissionsAndroid.RESULTS.GRANTED) {
          // Start downloading
          downloadFile();
          console.log('Storage Permission Granted.');
        } else {
          // If permission denied then show alert
          Alert.alert('Error', 'Storage Permission Not Granted');
        }
      } catch (err) {
        // To handle permission related exception
        console.log('++++' + err);
      }
    }

This is my AndroidManifest.xml file

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
  <uses-permission android:name="android.permission.CAMERA"/>
  <application android:name=".MainApplication" android:usesCleartextTraffic="true" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme">
    <activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:exported="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
      </intent-filter>
    </activity>
  </application>
</manifest>

Please help me with fixing the issue. Thanks in Advance.

Edit: targetSDKVersion : 33 trying to test the app in Android 13

Upvotes: 15

Views: 13702

Answers (3)

Nikitas IO
Nikitas IO

Reputation: 1171

I had the same issue for the POST_NOTIFICATIONS permission, so I looked around and found this github issue posted on react-native's repo that talks about this issue occurring for both the POST_NOTIFICATIONS and WRITE_EXTERNAL_STORAGE permissions.

POST_NOTIFICATIONS

Apparently, you don't ask for the permission if the API level is below 33 (Android 13), as Android doesn't recognize the permission for these versions.

That explains why in version older the PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS) method returns never_ask_again without any prompt instead of granted. In other words, Android doesn't know the permission on older APIs as it simply doesn't exist.

Therefore, the correct way to handle it is to explicitly check for the Android version before requesting the permission:

let notificationsPermissionCheck: PermissionStatus = "granted";
// The permission exists only for Android API versions bigger than 33 (Android 13),
// we can assume it's always granted beforehand
if (Platform.Version >= 33) {
  notificationsPermissionCheck = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
  );
}

console.log("notificationsPermissionCheck:", notificationsPermissionCheck);

WRITE_EXTERNAL_STORAGE

As for the WRITE_EXTERNAL_STORAGE permission, in the same github issue, it is stated that in Android 13 no WRITE_EXTERNAL_STORAGE permission is needed, and this example is given:

async function hasAndroidPermission() {
  if (Number(Platform.Version) >= 33) {
    return true;
  }

  const permission = PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE;

  const hasPermission = await PermissionsAndroid.check(permission);
  if (hasPermission) {
    return true;
  }

  const status = await PermissionsAndroid.request(permission);
  return status === 'granted';
}

Upvotes: 17

jayesh gurudayalani
jayesh gurudayalani

Reputation: 1691

Well as you are checking your code in API level 33 (Android 13) , you have to skip to check and ask permission for WRITE_EXTERNAL_STORAGE from api level 33 as new android versions have introduced restrictions for storage access and provide secure way to access data . It is suggested always to write your data to app directory only(cache directory) if it not necessary to show data to user . For more information related changes of storage , go thought this documentation

Links:-

https://developer.android.com/about/versions/11/privacy/storage

https://developer.android.com/training/data-storage/shared/media

https://stackoverflow.com/a/74296799/5696047

Upvotes: 2

klundn
klundn

Reputation: 46

This is probably the expected result from the permission flow on Android.

Starting in Android 11, if the user taps Deny for a specific permission more than once during your app's lifetime of installation on a device, the user doesn't see the system permissions dialog if your app requests that permission again. The user's action implies "don't ask again."

Taken from https://developer.android.com/about/versions/11/privacy/permissions#dialog-visibility

react-native-permission has a nice flow chart of the permission flow: https://github.com/zoontek/react-native-permissions#android-flow

Upvotes: 0

Related Questions