react-native-permissions
react-native-permissions copied to clipboard
Permissions are not asked again (marked as denied) if disabled manually in Settings (Android 12)
Bug summary
Permissions are prompt only once on Android 12. The status of the permission is only denied
, still the popup does not appear with request
nor requestMultiple
. Permission is flagged as denied
and the second time the permissions are asked the method freezes the app with both async-await
and then-catch
approaches (no errors are thrown). This happens when once granted, I go into the settings and manually deny one of the permissions.
The output of await checkMultiple(permissions_to_check)
is in my case:
"android.permission.ACCESS_FINE_LOCATION": "granted", "android.permission.BLUETOOTH_ADVERTISE": "denied", "android.permission.BLUETOOTH_CONNECT": "denied", "android.permission.BLUETOOTH_SCAN": "denied", "android.permission.CAMERA": "denied", "android.permission.READ_EXTERNAL_STORAGE": "granted", "android.permission.RECORD_AUDIO": "granted", "android.permission.WRITE_EXTERNAL_STORAGE": "granted"}
But still the BLUETOOTH and CAMERA permissions are not requested anymore in the app.
On LogCat I can see this:
2022-07-27 10:34:53.338 12792-12792/? V/GrantPermissionsViewModel: Permission grant result requestId=121482546543853**** callingUid=10*** callingPackage=**** permission=android.permission.CAMERA isImplicit=false result=2
Library version
3.6.0
Environment info
System:
OS: Windows 10 10.0.19044
CPU: (8) x64 Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
Memory: 5.20 GB / 15.87 GB
Binaries:
Node: 14.18.1 - C:\Users\MARCIN~1.PAB\AppData\Local\Temp\yarn--1658909889296-0.6736994793267819\node.CMD
Yarn: 1.22.15 - C:\Users\MARCIN~1.PAB\AppData\Local\Temp\yarn--1658909889296-0.6736994793267819\yarn.CMD
npm: 6.14.15 - C:\Program Files\nodejs\npm.CMD
Watchman: Not Found
SDKs:
Android SDK: Not Found
Windows SDK: Not Found
IDEs:
Android Studio: Version 2020.3.0.0 AI-203.7717.56.2031.7784292
Visual Studio: 16.3.29519.87 (Visual Studio Community 2019)
Languages:
Java: javac 11
Python: 3.10.0
npmPackages:
@react-native-community/cli: Not Found
react: 17.0.2 => 17.0.2
react-native: 0.63.4 => 0.63.4
react-native-windows: Not Found
npmGlobalPackages:
*react-native*: Not Found
Steps to reproduce
Happening on my personal device (Mi A2), custom ROM Streak Project (w/ root), based on Android 12.1.
- Into
App.tsx
insert some logic to check and require permission on a one-shotuseEffect(() => { <see example code> }, [])
- Ask for permissions and grant them. Launch the app normally and then close it.
- Go into settings of Android, deny manually one of the required permissions.
- Reopen the app: no permission dialog will be shown.
Reproducible sample code
const checkAndRequirePermissions = async (): Promise<void> => {
const required = [PERMISSIONS.ANDROID.CAMERA, PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE, PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE]
// First check if permissions are all requestable
console.log("Checking permissions...");
const permissionStatus = await checkMultiple(required);
// This will print permissions (denied the second time)
console.log(permissionStatus );
const unavailablePermissions: string[] = [];
Object.keys(permissionStatus).forEach((key) => {
if (
permissionStatus[key] === RESULTS.BLOCKED ||
permissionStatus[key] === RESULTS.UNAVAILABLE ||
permissionStatus[key] === RESULTS.LIMITED
) {
unavailablePermissions.push(key);
}
});
if (unavailablePermissions.length > 0) { throw false }
// Then request them (this will be the point on which app freezes)
console.log("Asking permissions...");
const requestPermissionStatus = await requestMultiple(required);
// This won't print the second time (app freezed)
console.log(requestPermissionStatus);
const notGrantedPermissions: string[] = [];
Object.keys(requestPermissionStatus).forEach((key) => {
if (requestPermissionStatus[key] !== RESULTS.GRANTED) {
notGrantedPermissions.push(key);
});
if (notGrantedPermissions.length > 0) { throw false }
return;
}
useEffect(() => {
checkAndRequestPermissions()
.then(() => {
console.log("yay!");
})
.catch((error) => {
console.log("nay :(", error);
})
});
// Launch the app, everything will work. Go to settings, deny one of the permissions, the permission won't be prompt again.
@Martinocom HI! I tried using the emulator (Android 13), my Pixel 4a (Android 12) and my Xiaomi A2 (stock, Android 10) and I cannot reproduce this behaviour (at least on React Native 0.69).
Did you tried with something else than a custom ROM / the latest RN version (ex: the example app)?
Haven't tested this on any other device nor project. In my free time I'll try to build on another phone (stock Android 11) and with a new clean fresh project on RN 0.63/0.69 only asking for permissions. I'll update you if I get something new.
We planned to use this library for permissions, since we cannot update at this time from 0.63 to 0.69, and we need to manage new Android bluetooth requests not implemented in the PermissionAndroid
in RN 0.63.
Hey! I was experiencing something similar, notably was trying to get Background geo permissions and it kept returning as denied.
I'm not 100% sure that its related to your issue, but in our case it was just about the order of the permissions.
Making sure to ask for location first, then geolocation after fixed it for us! Maybe something similar could be done on the code shared above.
Just sharing in case it helps anyone:)
I am also experiencing the same issue. I am using Samsung Galaxy S20 FE, Android 12. I am requesting only 1 permission in Android (android.permission.WRITE_EXTERNAL_STORAGE
), but I am using requestMultiple
and checkMultiple
because in iOS, I need 2 permissions (ios.permission.PHOTO_LIBRARY
, ios.permission.PHOTO_LIBRARY_ADD_ONLY
)
I initially reject / deny the request in Android. After that, both requestMultiple
and checkMultiple
will return denied
status in Android, without showing the request popup
In iOS, it still matches the description in ReadMe, initially the checkMultiple
will return denied
and will return blocked
or granted
or limited
in requestMultiple
I can reproduce this issue in android emulator using the repo example: Emulator : Android -12, API-31
Request permission throws: blocked check permission throws: denied
@ravi-poonia-lib What your describe is "normal". Check the Android flow. You have to request the permission to know if it's blocked.
Before, this library relied on SharedPreferences
to store the result in order to return blocked
on check, but we don't do it anymore since it breaks some permissions features on Android 11+ (ex: Going to the app settings and replace "Denied" by "Ask next time" - the storage was not reset and the lib continue to return blocked
. Only switching to "Grant" in settings worked). More infos in the v3.4.0 release note.
That's also why the built-in PermissionsAndroid
check
method return a boolean
(as we can't know if it's blocked
). This library still use statuses because unavailable
can be returned too - and to keep a multi platform API.
Consider this:
- Arriving on the screen, checking the permission
- The permission is
denied
- Display a button to request permission
- After pressing the button, it returns
blocked
- Prompt the user to got to app settings (with
Alert
, a nice explanation and anopenSettings
call)
It works on all platforms without special platform conditions, expect of course the permission arg passed to request
.
@Martinocom @williamliangwl Maybe I don't get your problem well, but is it what your are also talking about? @Martinocom When you said "Marked as denied", did you mean after a request or after a check?
EDIT: I added a warning in the README. The Android flow diagram wasn't enough.
As there is no feedback, I guess it was that.