☝🏼 React Native Permissions
An unified permissions API for React Native on iOS and Android.
Support
version | react-native version |
---|---|
2.0.0+ | 0.60.0+ |
2.0.0+ & jetify -r |
0.59.0 - 0.59.10 |
Setup
$ npm install --save react-native-permissions# --- or --- $ yarn add react-native-permissions
iOS
By default no permission handler is installed. Update your Podfile
by choosing the ones you want to check or request, then run pod install
.
target 'YourAwesomeProject' do # … permissions_path = '../node_modules/react-native-permissions/ios' pod 'Permission-BluetoothPeripheral', :path => "/BluetoothPeripheral.podspec" pod 'Permission-Calendars', :path => "/Calendars.podspec" pod 'Permission-Camera', :path => "/Camera.podspec" pod 'Permission-Contacts', :path => "/Contacts.podspec" pod 'Permission-FaceID', :path => "/FaceID.podspec" pod 'Permission-LocationAlways', :path => "/LocationAlways.podspec" pod 'Permission-LocationWhenInUse', :path => "/LocationWhenInUse.podspec" pod 'Permission-MediaLibrary', :path => "/MediaLibrary.podspec" pod 'Permission-Microphone', :path => "/Microphone.podspec" pod 'Permission-Motion', :path => "/Motion.podspec" pod 'Permission-Notifications', :path => "/Notifications.podspec" pod 'Permission-PhotoLibrary', :path => "/PhotoLibrary.podspec" pod 'Permission-Reminders', :path => "/Reminders.podspec" pod 'Permission-Siri', :path => "/Siri.podspec" pod 'Permission-SpeechRecognition', :path => "/SpeechRecognition.podspec" pod 'Permission-StoreKit', :path => "/StoreKit.podspec" end
⚠️ If you have the error Invalid RNPermission X. Should be one of: ()
, try to cleanup Xcode stale data with npx react-native-clean-project --remove-iOS-build --remove-iOS-pods && rm -fr ./node_modules
Then update your Info.plist
with wanted permissions usage descriptions:
<!-- 🚨 Keep only the permissions used in your app 🚨 --> NSAppleMusicUsageDescription YOUR TEXT NSBluetoothAlwaysUsageDescription YOUR TEXT NSBluetoothPeripheralUsageDescription YOUR TEXT NSCalendarsUsageDescription YOUR TEXT NSCameraUsageDescription YOUR TEXT NSContactsUsageDescription YOUR TEXT NSFaceIDUsageDescription YOUR TEXT NSLocationAlwaysAndWhenInUseUsageDescription YOUR TEXT NSLocationAlwaysUsageDescription YOUR TEXT NSLocationWhenInUseUsageDescription YOUR TEXT NSMicrophoneUsageDescription YOUR TEXT NSMotionUsageDescription YOUR TEXT NSPhotoLibraryUsageDescription YOUR TEXT NSRemindersUsageDescription YOUR TEXT NSSpeechRecognitionUsageDescription YOUR TEXT <!-- … -->
Android
Add all wanted permissions to your app android/app/src/main/res/AndroidManifest.xml
file:
<!-- 🚨 Keep only the permissions used in your app 🚨 --> <!-- … -->
🆘 Manual linking
Because this package targets React Native 0.60.0+, you will probably don't need to link it manually. Otherwise if it's not the case, follow this additional instructions:
👀 See manual linking instructions
iOS
Add this line to your ios/Podfile
file, then run pod install
.
target 'YourAwesomeProject' do # … pod 'RNPermissions', :path => '../node_modules/react-native-permissions'end
Android
- Add the following lines to
android/settings.gradle
:
include ':react-native-permissions'project(':react-native-permissions').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-permissions/android')
- Add the implementation line to the dependencies in
android/app/build.gradle
:
dependencies { // ... implementation project(':react-native-permissions')}
- Add the import and link the package in
MainApplication.java
:
// <- add the RNPermissionsPackage import
Understanding permission flow
As permissions are not handled in the same way on iOS and Android, this library provides an abstraction over the two platforms behaviors. To understand it a little better, take a look to these two flowcharts:
iOS flow
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ check(PERMISSIONS.IOS.CAMERA) ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
│
Is the feature available
on this device ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌─────────────────────┐
╚═════╝ │ RESULTS.UNAVAILABLE │
│ └─────────────────────┘
Is the permission
requestable ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌───────────────────┐
╚═════╝ │ RESULTS.BLOCKED / │
│ │ RESULTS.GRANTED │
▼ └───────────────────┘
┌────────────────┐
│ RESULTS.DENIED │
└────────────────┘
│
▼
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ request(PERMISSIONS.IOS.CAMERA) ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
│
Does the user accept
the request ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌─────────────────┐
╚═════╝ │ RESULTS.BLOCKED │
│ └─────────────────┘
▼
┌─────────────────┐
│ RESULTS.GRANTED │
└─────────────────┘
Android flow
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ check(PERMISSIONS.ANDROID.CAMERA) ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
│
Is the feature available
on this device ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌─────────────────────┐
╚═════╝ │ RESULTS.UNAVAILABLE │
│ └─────────────────────┘
Is the permission
requestable ?
│ ╔════╗
├───────────║ NO ║──────────────┐
│ ╚════╝ │
╔═════╗ ▼
║ YES ║ ┌───────────────────┐
╚═════╝ │ RESULTS.BLOCKED / │
│ │ RESULTS.GRANTED │
▼ └───────────────────┘
┌────────────────┐
│ RESULTS.DENIED │◀──────────────────────┐
└────────────────┘ │
│ │
▼ │
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ╔════╗
┃ request(PERMISSIONS.ANDROID.CAMERA) ┃ ║ NO ║
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ╚════╝
│ │
Does the user accept │
the request ? │
│ ╔════╗ Does the user check
├───────────║ NO ║─────"Never ask again" ?
│ ╚════╝ │
╔═════╗ ╔═════╗
║ YES ║ ║ YES ║
╚═════╝ ╚═════╝
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ RESULTS.GRANTED │ │ RESULTS.BLOCKED │
└─────────────────┘ └─────────────────┘
API
Supported permissions
; // Android permissions PERMISSIONSANDROIDACCEPT_HANDOVER;PERMISSIONSANDROIDACCESS_BACKGROUND_LOCATION;PERMISSIONSANDROIDACCESS_COARSE_LOCATION;PERMISSIONSANDROIDACCESS_FINE_LOCATION;PERMISSIONSANDROIDACTIVITY_RECOGNITION;PERMISSIONSANDROIDADD_VOICEMAIL;PERMISSIONSANDROIDANSWER_PHONE_CALLS;PERMISSIONSANDROIDBODY_SENSORS;PERMISSIONSANDROIDCALL_PHONE;PERMISSIONSANDROIDCAMERA;PERMISSIONSANDROIDGET_ACCOUNTS;PERMISSIONSANDROIDPROCESS_OUTGOING_CALLS;PERMISSIONSANDROIDREAD_CALENDAR;PERMISSIONSANDROIDREAD_CALL_LOG;PERMISSIONSANDROIDREAD_CONTACTS;PERMISSIONSANDROIDREAD_EXTERNAL_STORAGE;PERMISSIONSANDROIDREAD_PHONE_NUMBERS;PERMISSIONSANDROIDREAD_PHONE_STATE;PERMISSIONSANDROIDREAD_SMS;PERMISSIONSANDROIDRECEIVE_MMS;PERMISSIONSANDROIDRECEIVE_SMS;PERMISSIONSANDROIDRECEIVE_WAP_PUSH;PERMISSIONSANDROIDRECORD_AUDIO;PERMISSIONSANDROIDSEND_SMS;PERMISSIONSANDROIDUSE_SIP;PERMISSIONSANDROIDWRITE_CALENDAR;PERMISSIONSANDROIDWRITE_CALL_LOG;PERMISSIONSANDROIDWRITE_CONTACTS;PERMISSIONSANDROIDWRITE_EXTERNAL_STORAGE; // iOS permissions PERMISSIONSIOSBLUETOOTH_PERIPHERAL;PERMISSIONSIOSCALENDARS;PERMISSIONSIOSCAMERA;PERMISSIONSIOSCONTACTS;PERMISSIONSIOSFACE_ID;PERMISSIONSIOSLOCATION_ALWAYS;PERMISSIONSIOSLOCATION_WHEN_IN_USE;PERMISSIONSIOSMEDIA_LIBRARY;PERMISSIONSIOSMICROPHONE;PERMISSIONSIOSMOTION;PERMISSIONSIOSPHOTO_LIBRARY;PERMISSIONSIOSREMINDERS;PERMISSIONSIOSSIRI;PERMISSIONSIOSSPEECH_RECOGNITION;PERMISSIONSIOSSTOREKIT;
Permissions statuses
Permission checks and requests resolve into one of these statuses:
Return value | Notes |
---|---|
RESULTS.UNAVAILABLE |
This feature is not available (on this device / in this context) |
RESULTS.DENIED |
The permission has not been requested / is denied but requestable |
RESULTS.GRANTED |
The permission is granted |
RESULTS.BLOCKED |
The permission is denied and not requestable anymore |
Methods
// type used in usage examples;
check
Check one permission status.
;
; ;
request
Request one permission.
; ;
; ;
checkNotifications
Check notifications permission status and get notifications settings values.
;
; ;
requestNotifications
Request notifications permission status and get notifications settings values.
// only used on iOS; ;
; ;
openSettings
Open application settings.
;
; ;
Additional recipes
Check multiples permissions
; // can be done in parallelPromiseall // …;
Request multiples permissions
⚠️ It's a very bad UX pattern, avoid doing it!
; // should be done in sequence { const cameraStatus = await ; const contactsStatus = await ; return cameraStatus contactsStatus;} console;