zoontek / react-native-permissions

An unified permissions API for React Native on iOS, Android and Windows.
MIT License
4.1k stars 836 forks source link

[Android] Can't request for permission on denied access #675

Closed isaac-tcs closed 2 years ago

isaac-tcs commented 2 years ago

Bug summary

I'm using Pixel 4 API 30 emulator.

According to the Android flow on the README, if the user doesn't check "Never ask again?", the status goes back to DENIED. When I ran it on my emulator, it didn't had "Never ask again?" section and the result from checkMultiple() returned denied state.

But when I try to ask for permission again (after denying), permission modal won't show. It acts like BLOCKED state. Not sure if Pixel 4 api 30 automatically accepts denied access with never ask again option or there's something wrong with my code. Please help.

app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.terraclose">

  <uses-permission android:name="android.permission.CAMERA"/>
  <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

  <!-- live Streaming -->
  <uses-feature android:name="android.hardware.camera"/>
  <uses-feature android:name="android.hardware.camera.autofocus"/>

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:allowBackup="false"
      android:usesCleartextTraffic="true"
      android:theme="@style/AppTheme"
      android:networkSecurityConfig="@xml/network_security_config"
      android:requestLegacyExternalStorage="true">
      <!-- Change the value to true to enable pop-up for in foreground on receiving remote notifications (for prevent duplicating while showing local notifications set this to false) -->
        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_foreground"
                    android:value="false"/>
        <!-- Change the resource name to your App's accent color - or any other color you want -->
        <meta-data  android:name="com.dieam.reactnativepushnotification.notification_color"
                    android:resource="@color/white"/> <!-- or @android:color/{name} to use a standard color -->

      <meta-data android:name="com.google.android.geo.API_KEY"
       android:value="AIzaSyBvy_V9amO72NvCAcQM7foCayB19aJVQ4c"/>

      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
        android:launchMode="singleTask"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize"
        >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
    </application>
</manifest>
if (Platform.OS == 'ios') {
      check(PERMISSIONS.IOS.PHOTO_LIBRARY)
        .then(result => {
          if (result == RESULTS.BLOCKED) {
            setIosPermissionModal(true);
            return;
          }
        })
        .catch(error => {
          console.log('ios permission check error', error);
        });
    }
    if (Platform.OS == 'android') {
      checkMultiple([
        PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
        PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
      ])
        .then(result => {
          console.log('result', result);
          if (
            result[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] == RESULTS.BLOCKED
          ) {
            console.log('blocked??????????');                // this never fires
          }
          if (
            result[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] ==
              RESULTS.DENIED ||
            result[PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE == RESULTS.DENIED]
          ) {
            requestMultiple([
              PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
              PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
            ]).then(statuses => {
              console.log(
                'Camera',
                statuses[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE],
              );
              console.log(
                'FaceID',
                statuses[PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE],
              );
            });
            setAndroidPermissionModal(true);
            return;
          }
        })
        .catch(error => console.log('android permission check error', error));
    }

Library version

3.2.0

Environment info

System:
    OS: macOS 12.1
    CPU: (8) arm64 Apple M1
    Memory: 189.00 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.13.2 - /usr/local/bin/node
    Yarn: 1.22.11 - ~/isaac/terracloseFront/node_modules/.bin/yarn
    npm: 8.1.2 - /usr/local/bin/npm
    Watchman: 2022.01.17.00 - /opt/homebrew/bin/watchman
  Managers:
    CocoaPods: 1.11.2 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.2, iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3
    Android SDK: Not Found
  IDEs:
    Android Studio: 2020.3 AI-203.7717.56.2031.7935034
    Xcode: 13.2.1/13C100 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.14 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.1 => 17.0.1 
    react-native: 0.64.2 => 0.64.2 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Steps to reproduce

  1. On Android, ask for permission for PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE, PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE, and deny it.
  2. Revisit the screen from step 1 and ask for permission if current permission is DEINIED

Reproducible sample code

const askForPermission = () => {
  if (Platform.OS == 'ios') {
      check(PERMISSIONS.IOS.PHOTO_LIBRARY)
        .then(result => {
          if (result == RESULTS.BLOCKED) {
            setIosPermissionModal(true);
            return;
          }
        })
        .catch(error => {
          console.log('ios permission check error', error);
        });
    }
    if (Platform.OS == 'android') {
      checkMultiple([
        PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
        PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
      ])
        .then(result => {
          console.log('result', result);
          if (
            result[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] == RESULTS.BLOCKED
          ) {
            console.log('this is blocked');
          }
          if (
            result[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] ==
              RESULTS.DENIED ||
            result[PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE == RESULTS.DENIED]
          ) {
            requestMultiple([
              PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
              PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
            ]).then(statuses => {
              console.log(
                'Camera',
                statuses[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE],
              );
              console.log(
                'FaceID',
                statuses[PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE],
              );
            });
            setAndroidPermissionModal(true);
            return;
          }
        })
        .catch(error => console.log('android permission check error', error));
}
zoontek commented 2 years ago

This "Never ask again" checkbox does not exists anymore on latest Android versions. It's not a bug, the schema has to be updated.