react-native-permissions vs react-native-fs vs react-native-image-picker vs expo-media-library vs react-native-camera
React Native Media Handling Libraries Comparison
1 Year
react-native-permissionsreact-native-fsreact-native-image-pickerexpo-media-libraryreact-native-cameraSimilar Packages:
What's React Native Media Handling Libraries?

These libraries provide essential functionalities for handling media in React Native applications, including image and video access, file system management, and permissions. They enable developers to create rich media experiences by allowing users to access their device's media library, capture photos and videos, manage files, and handle permissions seamlessly. Each library serves a specific purpose and can be used independently or in conjunction with others to enhance the media capabilities of a mobile application.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
react-native-permissions555,1584,166372 kB10a month agoMIT
react-native-fs430,5775,001570 kB622-MIT
react-native-image-picker355,9928,519189 kB3082 days agoMIT
expo-media-library102,41537,771299 kB79815 days agoMIT
react-native-camera81,0709,645-1443 years agoMIT AND Apache-2.0 AND BSD-3-Clause
Feature Comparison: react-native-permissions vs react-native-fs vs react-native-image-picker vs expo-media-library vs react-native-camera

Media Access

  • react-native-permissions:

    react-native-permissions does not handle media access directly but is essential for managing permissions required for accessing media libraries and camera functionalities. It ensures that your app can request the necessary permissions before attempting to access media.

  • react-native-fs:

    react-native-fs focuses on file system access rather than media libraries. It allows reading and writing files to the device's storage, enabling developers to manage media files programmatically after they have been captured or selected by other means.

  • react-native-image-picker:

    react-native-image-picker provides a simple interface for accessing the device's media library, allowing users to pick images or videos. It supports both camera capture and library selection, making it easy to integrate media selection into applications.

  • expo-media-library:

    expo-media-library provides a unified API to access and manage media assets stored on the device. It allows developers to retrieve photos and videos, create albums, and manage media permissions seamlessly within an Expo environment.

  • react-native-camera:

    react-native-camera does not directly access media libraries but allows developers to capture images and videos using the device's camera. It provides real-time camera previews and supports various camera configurations, making it ideal for applications that require direct camera interaction.

Camera Functionality

  • react-native-permissions:

    react-native-permissions does not provide camera functionalities. It is used to manage permissions needed for accessing the camera or media libraries, ensuring that your app can request and handle permissions appropriately.

  • react-native-fs:

    react-native-fs does not provide any camera functionalities. It is focused on file system operations, allowing developers to manage files after they have been captured or selected through other means.

  • react-native-image-picker:

    react-native-image-picker allows capturing images and videos using the device's camera but does not provide advanced camera controls. It is primarily designed for media selection rather than comprehensive camera management.

  • expo-media-library:

    expo-media-library does not provide camera functionalities; it is solely focused on media asset management. For camera features, developers would need to integrate additional libraries like react-native-camera.

  • react-native-camera:

    react-native-camera offers extensive camera functionalities, including capturing photos, recording videos, and barcode scanning. It supports various camera types and configurations, making it suitable for applications requiring direct camera interaction.

File Management

  • react-native-permissions:

    react-native-permissions does not provide file management capabilities. It focuses on managing permissions required for accessing files and media.

  • react-native-fs:

    react-native-fs excels in file management, providing a comprehensive API for reading, writing, and managing files on the device's file system. It is ideal for applications that require extensive file handling capabilities.

  • react-native-image-picker:

    react-native-image-picker allows users to select media files but does not provide file management functionalities. Selected media can be managed using other libraries once retrieved.

  • expo-media-library:

    expo-media-library allows limited file management capabilities, primarily focused on media assets. It enables developers to create albums and manage media files but does not provide full file system access.

  • react-native-camera:

    react-native-camera does not handle file management directly. It captures images and videos, which can then be managed using other libraries like react-native-fs for storage and manipulation.

Ease of Use

  • react-native-permissions:

    react-native-permissions is straightforward to use for managing permissions, but developers need to understand the permission model of mobile platforms to implement it correctly.

  • react-native-fs:

    react-native-fs is relatively easy to use for basic file operations, but developers may need to understand the underlying file system structure to manage files effectively.

  • react-native-image-picker:

    react-native-image-picker is user-friendly and easy to integrate, providing a simple interface for media selection. It is suitable for developers looking for quick implementation of media picking features.

  • expo-media-library:

    expo-media-library is designed for ease of use within Expo projects, providing a straightforward API that abstracts complex native code interactions. It is user-friendly and ideal for developers familiar with Expo.

  • react-native-camera:

    react-native-camera has a steeper learning curve due to its extensive features and configurations. Developers may need to familiarize themselves with camera settings and capabilities to utilize it effectively.

Platform Compatibility

  • react-native-permissions:

    react-native-permissions supports both iOS and Android, allowing developers to manage permissions across platforms effectively.

  • react-native-fs:

    react-native-fs is compatible with both platforms, allowing file system access on iOS and Android. However, file paths and permissions may differ between platforms, requiring careful handling.

  • react-native-image-picker:

    react-native-image-picker is designed for cross-platform compatibility, providing a consistent interface for accessing media on both iOS and Android devices.

  • expo-media-library:

    expo-media-library is compatible with both iOS and Android devices within the Expo ecosystem, making it a great choice for cross-platform applications.

  • react-native-camera:

    react-native-camera supports both iOS and Android, but developers need to ensure proper configuration for each platform, as there may be differences in camera capabilities and settings.

How to Choose: react-native-permissions vs react-native-fs vs react-native-image-picker vs expo-media-library vs react-native-camera
  • react-native-permissions:

    Choose react-native-permissions when your app requires fine-grained control over permissions for accessing device features. This library allows you to request and check permissions for various functionalities, ensuring that your app complies with user privacy and platform requirements.

  • react-native-fs:

    Opt for react-native-fs when you need to perform file system operations, such as reading, writing, and managing files on the device. This library is ideal for applications that require file handling capabilities beyond media, such as downloading files or managing app-specific data storage.

  • react-native-image-picker:

    Use react-native-image-picker if your application needs to allow users to select images or videos from their device's library or capture new media using the camera. It provides a simple interface for accessing the media picker and is great for apps that focus on user-generated content.

  • expo-media-library:

    Choose expo-media-library if you are developing an Expo-managed React Native app and need a simple way to access and manage media assets like photos and videos from the device's library. It provides a straightforward API for retrieving and manipulating media files without dealing with native code.

  • react-native-camera:

    Select react-native-camera if you require advanced camera functionalities, such as capturing photos, recording videos, or scanning barcodes. It offers a comprehensive set of features for camera control and is suitable for applications that need real-time camera access and manipulation.

README for react-native-permissions

☝🏼 react-native-permissions

An unified permissions API for React Native on iOS, Android and Windows.
(For Windows only builds 18362 and later are supported)

mit licence npm version npm downloads
platform - android platform - ios platform - windows

Support

This library follows the React Native releases support policy.
It is supporting the latest version, and the two previous minor series.

Setup

$ npm i -S react-native-permissions
# --- or ---
$ yarn add react-native-permissions

iOS

  1. By default, no permissions are available. First, require the setup script in your Podfile:
# Transform this into a `node_require` generic function:
- # Resolve react_native_pods.rb with node to allow for hoisting
- require Pod::Executable.execute_command('node', ['-p',
-   'require.resolve(
-     "react-native/scripts/react_native_pods.rb",
-     {paths: [process.argv[1]]},
-   )', __dir__]).strip

+ def node_require(script)
+   # Resolve script with node to allow for hoisting
+   require Pod::Executable.execute_command('node', ['-p',
+     "require.resolve(
+       '#{script}',
+       {paths: [process.argv[1]]},
+     )", __dir__]).strip
+ end

# Use it to require both react-native's and this package's scripts:
+ node_require('react-native/scripts/react_native_pods.rb')
+ node_require('react-native-permissions/scripts/setup.rb')
  1. In the same Podfile, call setup_permissions with the permissions you need. Only the permissions specified here will be added:
# …

platform :ios, min_ios_version_supported
prepare_react_native_project!

# ⬇️ uncomment the permissions you need
setup_permissions([
  # 'AppTrackingTransparency',
  # 'Bluetooth',
  # 'Calendars',
  # 'CalendarsWriteOnly',
  # 'Camera',
  # 'Contacts',
  # 'FaceID',
  # 'LocationAccuracy',
  # 'LocationAlways',
  # 'LocationWhenInUse',
  # 'MediaLibrary',
  # 'Microphone',
  # 'Motion',
  # 'Notifications',
  # 'PhotoLibrary',
  # 'PhotoLibraryAddOnly',
  # 'Reminders',
  # 'Siri',
  # 'SpeechRecognition',
  # 'StoreKit',
])

# …
  1. Then execute pod install in your ios directory (📌  Note that it must be re-executed each time you update this config).
  2. Finally, add the corresponding permissions usage descriptions to your Info.plist. For example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>

  <!-- 🚨 Keep only the permissions specified in `setup_permissions` 🚨 -->

  <key>NSAppleMusicUsageDescription</key>
  <string>[REASON]</string>
  <key>NSBluetoothAlwaysUsageDescription</key>
  <string>[REASON]</string>
  <key>NSBluetoothPeripheralUsageDescription</key>
  <string>[REASON]</string>
  <key>NSCalendarsFullAccessUsageDescription</key>
  <string>[REASON]</string>
  <key>NSCalendarsWriteOnlyAccessUsageDescription</key>
  <string>[REASON]</string>
  <key>NSCameraUsageDescription</key>
  <string>[REASON]</string>
  <key>NSContactsUsageDescription</key>
  <string>[REASON]</string>
  <key>NSFaceIDUsageDescription</key>
  <string>[REASON]</string>
  <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
  <string>[REASON]</string>
  <key>NSLocationTemporaryUsageDescriptionDictionary</key>
  <dict>
    <key>YOUR-PURPOSE-KEY</key>
    <string>[REASON]</string>
  </dict>
  <key>NSLocationWhenInUseUsageDescription</key>
  <string>[REASON]</string>
  <key>NSMicrophoneUsageDescription</key>
  <string>[REASON]</string>
  <key>NSMotionUsageDescription</key>
  <string>[REASON]</string>
  <key>NSPhotoLibraryUsageDescription</key>
  <string>[REASON]</string>
  <key>NSPhotoLibraryAddUsageDescription</key>
  <string>[REASON]</string>
  <key>NSRemindersFullAccessUsageDescription</key>
  <string>[REASON]</string>
  <key>NSSpeechRecognitionUsageDescription</key>
  <string>[REASON]</string>
  <key>NSSiriUsageDescription</key>
  <string>[REASON]</string>
  <key>NSUserTrackingUsageDescription</key>
  <string>[REASON]</string>

  <!-- … -->

</dict>
</plist>

Android

Add all wanted permissions to your app android/app/src/main/AndroidManifest.xml file:

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

  <!-- 🚨 Keep only the permissions used in your app 🚨 -->

  <uses-permission android:name="android.permission.ACCEPT_HANDOVER" />
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
  <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
  <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
  <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
  <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
  <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
  <uses-permission android:name="android.permission.BODY_SENSORS" />
  <uses-permission android:name="android.permission.BODY_SENSORS_BACKGROUND" />
  <uses-permission android:name="android.permission.CALL_PHONE" />
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.GET_ACCOUNTS" />
  <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
  <uses-permission android:name="android.permission.READ_CALENDAR" />
  <uses-permission android:name="android.permission.READ_CALL_LOG" />
  <uses-permission android:name="android.permission.READ_CONTACTS" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
  <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
  <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
  <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  <uses-permission android:name="android.permission.READ_SMS" />
  <uses-permission android:name="android.permission.RECEIVE_MMS" />
  <uses-permission android:name="android.permission.RECEIVE_SMS" />
  <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
  <uses-permission android:name="android.permission.RECORD_AUDIO" />
  <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
  <uses-permission android:name="android.permission.SEND_SMS" />
  <uses-permission android:name="android.permission.USE_SIP" />
  <uses-permission android:name="android.permission.UWB_RANGING" />
  <uses-permission android:name="android.permission.WRITE_CALENDAR" />
  <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
  <uses-permission android:name="android.permission.WRITE_CONTACTS" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

  <!-- … -->

</manifest>

Expo

If you use Expo, the previous sections don't apply. Instead just update your app.json file with the corresponding values, but using the syntax exemplified below:

{
  "expo": {
    "name": "Awesome app",
    "plugins": [
      [
        "react-native-permissions",
        {
          // Add setup_permissions to your Podfile (see iOS setup - steps 1, 2 and 3)
          "iosPermissions": [
            "Camera",
            "Microphone"
          ]
        }
      ]
    ],
    "ios": {
      // Add descriptions to your Info.plist (see iOS setup - step 4)
      "infoPlist": {
        "NSCameraUsageDescription": "[REASON]",
        "NSMicrophoneUsageDescription": "[REASON]"
      }
    },
    "android": {
      // Add permissions to your AndroidManifest.xml (see Android setup)
      "permissions": [
        "android.permission.CAMERA",
        "android.permission.RECORD_AUDIO"
      ]
    }
  }
}

Windows

Open the project solution file from the windows folder. In the app project open Package.appxmanifest file. From there you can select which capabilites you want your app to support.

🆘 Manual linking

Because this package targets recent React Native versions, you probably don't need to link it manually. But if you have a special case, follow these 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

  1. 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')
  1. Add the implementation line to the dependencies in android/app/build.gradle:
dependencies {
  // ...
  implementation project(':react-native-permissions')
}
  1. Add the import and link the package in MainApplication.java:
import com.zoontek.rnpermissions.RNPermissionsPackage; // <- add the RNPermissionsPackage import

public class MainApplication extends Application implements ReactApplication {

  // …

  @Override
  protected List<ReactPackage> getPackages() {
    @SuppressWarnings("UnnecessaryLocalVariable")
    List<ReactPackage> packages = new PackageList(this).getPackages();
    // …
    packages.add(new RNPermissionsPackage());
    return packages;
  }

  // …
}

Windows

  1. In windows/myapp.sln add the RNCConfig project to your solution:
  • Open the solution in Visual Studio 2019
  • Right-click Solution icon in Solution Explorer > Add > Existing Project
  • Select node_modules\react-native-permissions\windows\RNPermissions\RNPermissions.vcxproj
  1. In windows/myapp/myapp.vcxproj ad a reference to RNPermissions to your main application project. From Visual Studio 2019:
  • Right-click main application project > Add > Reference...
  • Check RNPermissions from Solution Projects.
  1. In pch.h add #include "winrt/RNPermissions.h".

  2. In app.cpp add PackageProviders().Append(winrt::RNPermissions::ReactPackageProvider()); before InitializeComponent();.

Understanding permission flow

As permissions are not handled in the same way on iOS, Android and Windows, this library provides an abstraction over the three platforms behaviors. To understand it a little better, take a look to this flowchart:

 ┏━━━━━━━━━━━━━━━━━━━━━━━━┓
 ┃ check(PERMISSIONS.X.Y) ┃
 ┗━━━━━━━━━━━━━━━━━━━━━━━━┛
              │                                ┌─────────────────────┐
  Is the feature available ───────── NO ─────▶ │ RESULTS.UNAVAILABLE │
      on this device ?                         └─────────────────────┘
              │
             YES
              │                                ┌───────────────────────────┐
      Is the permission ─────────── YES ─────▶ │ RESULTS.GRANTED / LIMITED │
      already granted ?                        └───────────────────────────┘
              │
              NO
              │                                ┌─────────────────┐
Is the permission requestable, ───── NO ─────▶ │ RESULTS.BLOCKED │
 or is the platform Android ?                  └─────────────────┘
              │
             YES
              │
              ▼
     ┌────────────────┐
     │ RESULTS.DENIED │
     └────────────────┘
              │
              ▼
 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 ┃ request(PERMISSIONS.X.Y) ┃◀─────────────────────────┐
 ┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛                          │
              │                                       YES
              │                                        │
    Did the user see and ──────── NO ──────── Is the permission
    accept the request ?                      still requestable ?
              │                                        │
             YES                                       NO
              │                                        │
              ▼                                        ▼
┌───────────────────────────┐                 ┌─────────────────┐
│ RESULTS.GRANTED / LIMITED │                 │ RESULTS.BLOCKED │
└───────────────────────────┘                 └─────────────────┘

This can be implemented as follows:

  • check the permission status
  • If granted, use the feature
  • If blocked, display a screen prompting the user to go to settings (using openSettings) (This will not be shown on Android)
  • If denied, display a button to request permission:
    • If granted, use the feature
    • If blocked, display an alert prompting the user to go to settings (using openSettings)

The user experience (UX) is excellent on iOS and acceptable on Android, considering the platform's limitations.

API

Supported permissions

Android permissions
import {PERMISSIONS} from 'react-native-permissions';

PERMISSIONS.ANDROID.ACCEPT_HANDOVER;
PERMISSIONS.ANDROID.ACCESS_BACKGROUND_LOCATION;
PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION;
PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION;
PERMISSIONS.ANDROID.ACCESS_MEDIA_LOCATION;
PERMISSIONS.ANDROID.ACTIVITY_RECOGNITION;
PERMISSIONS.ANDROID.ADD_VOICEMAIL;
PERMISSIONS.ANDROID.ANSWER_PHONE_CALLS;
PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE;
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT;
PERMISSIONS.ANDROID.BLUETOOTH_SCAN;
PERMISSIONS.ANDROID.BODY_SENSORS;
PERMISSIONS.ANDROID.BODY_SENSORS_BACKGROUND;
PERMISSIONS.ANDROID.CALL_PHONE;
PERMISSIONS.ANDROID.CAMERA;
PERMISSIONS.ANDROID.GET_ACCOUNTS;
PERMISSIONS.ANDROID.NEARBY_WIFI_DEVICES;
PERMISSIONS.ANDROID.POST_NOTIFICATIONS;
PERMISSIONS.ANDROID.PROCESS_OUTGOING_CALLS;
PERMISSIONS.ANDROID.READ_CALENDAR;
PERMISSIONS.ANDROID.READ_CALL_LOG;
PERMISSIONS.ANDROID.READ_CONTACTS;
PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE;
PERMISSIONS.ANDROID.READ_MEDIA_AUDIO;
PERMISSIONS.ANDROID.READ_MEDIA_IMAGES;
PERMISSIONS.ANDROID.READ_MEDIA_VIDEO;
PERMISSIONS.ANDROID.READ_MEDIA_VISUAL_USER_SELECTED;
PERMISSIONS.ANDROID.READ_PHONE_NUMBERS;
PERMISSIONS.ANDROID.READ_PHONE_STATE;
PERMISSIONS.ANDROID.READ_SMS;
PERMISSIONS.ANDROID.RECEIVE_MMS;
PERMISSIONS.ANDROID.RECEIVE_SMS;
PERMISSIONS.ANDROID.RECEIVE_WAP_PUSH;
PERMISSIONS.ANDROID.RECORD_AUDIO;
PERMISSIONS.ANDROID.SEND_SMS;
PERMISSIONS.ANDROID.USE_SIP;
PERMISSIONS.ANDROID.UWB_RANGING;
PERMISSIONS.ANDROID.WRITE_CALENDAR;
PERMISSIONS.ANDROID.WRITE_CALL_LOG;
PERMISSIONS.ANDROID.WRITE_CONTACTS;
PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE;
iOS permissions
import {PERMISSIONS} from 'react-native-permissions';

PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY;
PERMISSIONS.IOS.BLUETOOTH;
PERMISSIONS.IOS.CALENDARS;
PERMISSIONS.IOS.CALENDARS_WRITE_ONLY;
PERMISSIONS.IOS.CAMERA;
PERMISSIONS.IOS.CONTACTS;
PERMISSIONS.IOS.FACE_ID;
PERMISSIONS.IOS.LOCATION_ALWAYS;
PERMISSIONS.IOS.LOCATION_WHEN_IN_USE;
PERMISSIONS.IOS.MEDIA_LIBRARY;
PERMISSIONS.IOS.MICROPHONE;
PERMISSIONS.IOS.MOTION;
PERMISSIONS.IOS.PHOTO_LIBRARY;
PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY;
PERMISSIONS.IOS.REMINDERS;
PERMISSIONS.IOS.SIRI;
PERMISSIONS.IOS.SPEECH_RECOGNITION;
PERMISSIONS.IOS.STOREKIT;
Windows permissions
import {PERMISSIONS} from 'react-native-permissions';

PERMISSIONS.WINDOWS.ACCESSORY_MANAGER;
PERMISSIONS.WINDOWS.ACTIVITY;
PERMISSIONS.WINDOWS.ALLOW_ELEVATION;
PERMISSIONS.WINDOWS.ALL_APP_MODS;
PERMISSIONS.WINDOWS.ALL_JOYN;
PERMISSIONS.WINDOWS.APPOINTMENTS;
PERMISSIONS.WINDOWS.APPOINTMENTS_SYSTEM;
PERMISSIONS.WINDOWS.APP_BROADCAST_SERVICES;
PERMISSIONS.WINDOWS.APP_CAPTURE_SERVICES;
PERMISSIONS.WINDOWS.APP_CAPTURE_SETTINGS;
PERMISSIONS.WINDOWS.APP_DIAGNOSTICS;
PERMISSIONS.WINDOWS.APP_LICENSING;
PERMISSIONS.WINDOWS.AUDIO_DEVICE_CONFIGURATION;
PERMISSIONS.WINDOWS.BACKGROUND_MEDIA_PLAYBACK;
PERMISSIONS.WINDOWS.BACKGROUND_MEDIA_RECORDING;
PERMISSIONS.WINDOWS.BACKGROUND_SPATIAL_PERCEPTION;
PERMISSIONS.WINDOWS.BACKGROUND_VOIP;
PERMISSIONS.WINDOWS.BLOCKED_CHAT_MESSAGES;
PERMISSIONS.WINDOWS.BLUETOOTH;
PERMISSIONS.WINDOWS.BROAD_FILE_SYSTEM_ACCESS;
PERMISSIONS.WINDOWS.CAMERA_PROCESSING_EXTENSION;
PERMISSIONS.WINDOWS.CELLULAR_DEVICE_CONTROL;
PERMISSIONS.WINDOWS.CELLULAR_DEVICE_IDENTITY;
PERMISSIONS.WINDOWS.CELLULAR_MESSAGING;
PERMISSIONS.WINDOWS.CHAT_SYSTEM;
PERMISSIONS.WINDOWS.CODE_GENERATION;
PERMISSIONS.WINDOWS.CONFIRM_APP_CLOSE;
PERMISSIONS.WINDOWS.CONTACTS;
PERMISSIONS.WINDOWS.CONTACTS_SYSTEM;
PERMISSIONS.WINDOWS.CORTANA_PERMISSIONS;
PERMISSIONS.WINDOWS.CORTANA_SPEECH_ACCESSORY;
PERMISSIONS.WINDOWS.CUSTOM_INSTALL_ACTIONS;
PERMISSIONS.WINDOWS.DEVELOPMENT_MODE_NETWORK;
PERMISSIONS.WINDOWS.DEVICE_MANAGEMENT_DM_ACCOUNT;
PERMISSIONS.WINDOWS.DEVICE_MANAGEMENT_EMAIL_ACCOUNT;
PERMISSIONS.WINDOWS.DEVICE_MANAGEMENT_FOUNDATION;
PERMISSIONS.WINDOWS.DEVICE_MANAGEMENT_WAP_SECURITY_POLICIES;
PERMISSIONS.WINDOWS.DEVICE_PORTAL_PROVIDER;
PERMISSIONS.WINDOWS.DEVICE_UNLOCK;
PERMISSIONS.WINDOWS.DOCUMENTS_LIBRARY;
PERMISSIONS.WINDOWS.DUAL_SIM_TILES;
PERMISSIONS.WINDOWS.EMAIL;
PERMISSIONS.WINDOWS.EMAIL_SYSTEM;
PERMISSIONS.WINDOWS.ENTERPRISE_AUTHENTICATION;
PERMISSIONS.WINDOWS.ENTERPRISE_CLOUD_S_S_O;
PERMISSIONS.WINDOWS.ENTERPRISE_DATA_POLICY;
PERMISSIONS.WINDOWS.ENTERPRISE_DEVICE_LOCKDOWN;
PERMISSIONS.WINDOWS.EXPANDED_RESOURCES;
PERMISSIONS.WINDOWS.EXTENDED_BACKGROUND_TASK_TIME;
PERMISSIONS.WINDOWS.EXTENDED_EXECUTION_BACKGROUND_AUDIO;
PERMISSIONS.WINDOWS.EXTENDED_EXECUTION_CRITICAL;
PERMISSIONS.WINDOWS.EXTENDED_EXECUTION_UNCONSTRAINED;
PERMISSIONS.WINDOWS.FIRST_SIGN_IN_SETTINGS;
PERMISSIONS.WINDOWS.GAME_BAR_SERVICES;
PERMISSIONS.WINDOWS.GAME_LIST;
PERMISSIONS.WINDOWS.GAME_MONITOR;
PERMISSIONS.WINDOWS.GAZE_INPUT;
PERMISSIONS.WINDOWS.GLOBAL_MEDIA_CONTROL;
PERMISSIONS.WINDOWS.HUMANINTERFACEDEVICE;
PERMISSIONS.WINDOWS.INPUT_FOREGROUND_OBSERVATION;
PERMISSIONS.WINDOWS.INPUT_INJECTION_BROKERED;
PERMISSIONS.WINDOWS.INPUT_OBSERVATION;
PERMISSIONS.WINDOWS.INPUT_SUPPRESSION;
PERMISSIONS.WINDOWS.INTERNET_CLIENT;
PERMISSIONS.WINDOWS.INTERNET_CLIENT_SERVER;
PERMISSIONS.WINDOWS.INTEROP_SERVICES;
PERMISSIONS.WINDOWS.IOT;
PERMISSIONS.WINDOWS.LOCAL_SYSTEM_SERVICES;
PERMISSIONS.WINDOWS.LOCATION;
PERMISSIONS.WINDOWS.LOCATION_HISTORY;
PERMISSIONS.WINDOWS.LOCATION_SYSTEM;
PERMISSIONS.WINDOWS.LOW_LEVEL;
PERMISSIONS.WINDOWS.LOW_LEVEL_DEVICES;
PERMISSIONS.WINDOWS.MICROPHONE;
PERMISSIONS.WINDOWS.MOBILE;
PERMISSIONS.WINDOWS.MODIFIABLE_APP;
PERMISSIONS.WINDOWS.MUSIC_LIBRARY;
PERMISSIONS.WINDOWS.NETWORKING_VPN_PROVIDER;
PERMISSIONS.WINDOWS.NETWORK_CONNECTION_MANAGER_PROVISIONING;
PERMISSIONS.WINDOWS.NETWORK_DATA_PLAN_PROVISIONING;
PERMISSIONS.WINDOWS.NETWORK_DATA_USAGE_MANAGEMENT;
PERMISSIONS.WINDOWS.OEM_DEPLOYMENT;
PERMISSIONS.WINDOWS.OEM_PUBLIC_DIRECTORY;
PERMISSIONS.WINDOWS.ONE_PROCESS_VOIP;
PERMISSIONS.WINDOWS.OPTICAL;
PERMISSIONS.WINDOWS.PACKAGED_SERVICES;
PERMISSIONS.WINDOWS.PACKAGES_SERVICES;
PERMISSIONS.WINDOWS.PACKAGE_MANAGEMENT;
PERMISSIONS.WINDOWS.PACKAGE_POLICY_SYSTEM;
PERMISSIONS.WINDOWS.PACKAGE_QUERY;
PERMISSIONS.WINDOWS.PACKAGE_WRITE_REDIRECTION_COMPATIBILITY_SHIM;
PERMISSIONS.WINDOWS.PHONE_CALL;
PERMISSIONS.WINDOWS.PHONE_CALL_HISTORY;
PERMISSIONS.WINDOWS.PHONE_CALL_HISTORY_SYSTEM;
PERMISSIONS.WINDOWS.PHONE_LINE_TRANSPORT_MANAGEMENT;
PERMISSIONS.WINDOWS.PICTURES_LIBRARY;
PERMISSIONS.WINDOWS.POINT_OF_SERVICE;
PERMISSIONS.WINDOWS.PREVIEW_INK_WORKSPACE;
PERMISSIONS.WINDOWS.PREVIEW_PEN_WORKSPACE;
PERMISSIONS.WINDOWS.PREVIEW_STORE;
PERMISSIONS.WINDOWS.PREVIEW_UI_COMPOSITION;
PERMISSIONS.WINDOWS.PRIVATE_NETWORK_CLIENT_SERVER;
PERMISSIONS.WINDOWS.PROTECTED_APP;
PERMISSIONS.WINDOWS.PROXIMITY;
PERMISSIONS.WINDOWS.RADIOS;
PERMISSIONS.WINDOWS.RECORDED_CALLS_FOLDER;
PERMISSIONS.WINDOWS.REMOTE_PASSPORT_AUTHENTICATION;
PERMISSIONS.WINDOWS.REMOTE_SYSTEM;
PERMISSIONS.WINDOWS.REMOVABLE_STORAGE;
PERMISSIONS.WINDOWS.RESCAP;
PERMISSIONS.WINDOWS.RUN_FULL_TRUST;
PERMISSIONS.WINDOWS.SCREEN_DUPLICATION;
PERMISSIONS.WINDOWS.SECONDARY_AUTHENTICATION_FACTOR;
PERMISSIONS.WINDOWS.SECURE_ASSESSMENT;
PERMISSIONS.WINDOWS.SERIALCOMMUNICATION;
PERMISSIONS.WINDOWS.SHARED_USER_CERTIFICATES;
PERMISSIONS.WINDOWS.SLAPI_QUERY_LICENSE_VALUE;
PERMISSIONS.WINDOWS.SMBIOS;
PERMISSIONS.WINDOWS.SMS_SEND;
PERMISSIONS.WINDOWS.SPATIAL_PERCEPTION;
PERMISSIONS.WINDOWS.START_SCREEN_MANAGEMENT;
PERMISSIONS.WINDOWS.STORE_LICENSE_MANAGEMENT;
PERMISSIONS.WINDOWS.SYSTEM_MANAGEMENT;
PERMISSIONS.WINDOWS.TARGETED_CONTENT;
PERMISSIONS.WINDOWS.TEAM_EDITION_DEVICE_CREDENTIAL;
PERMISSIONS.WINDOWS.TEAM_EDITION_EXPERIENCE;
PERMISSIONS.WINDOWS.TEAM_EDITION_VIEW;
PERMISSIONS.WINDOWS.UAP;
PERMISSIONS.WINDOWS.UI_AUTOMATION;
PERMISSIONS.WINDOWS.UNVIRTUALIZED_RESOURCES;
PERMISSIONS.WINDOWS.USB;
PERMISSIONS.WINDOWS.USER_ACCOUNT_INFORMATION;
PERMISSIONS.WINDOWS.USER_DATA_ACCOUNTS_PROVIDER;
PERMISSIONS.WINDOWS.USER_DATA_SYSTEM;
PERMISSIONS.WINDOWS.USER_PRINCIPAL_NAME;
PERMISSIONS.WINDOWS.USER_SYSTEM_ID;
PERMISSIONS.WINDOWS.VIDEOS_LIBRARY;
PERMISSIONS.WINDOWS.VOIP_CALL;
PERMISSIONS.WINDOWS.WALLET_SYSTEM;
PERMISSIONS.WINDOWS.WEBCAM;
PERMISSIONS.WINDOWS.WIFI_CONTROL;
PERMISSIONS.WINDOWS.XBOX_ACCESSORY_MANAGEMENT;

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.BLOCKED | The permission is denied and not requestable | | RESULTS.GRANTED | The permission is granted | | RESULTS.LIMITED | The permission is granted but with limitations
Only for iOS Contacts, PhotoLibrary, PhotoLibraryAddOnly and Notifications |

Types

type ValueOf<T> = T[keyof T];

type Permission =
  | ValueOf<typeof PERMISSIONS.ANDROID>
  | ValueOf<typeof PERMISSIONS.IOS>
  | ValueOf<typeof PERMISSIONS.WINDOWS>;

type PermissionStatus = ValueOf<typeof RESULTS>;

type RationaleObject = {
  title: string;
  message: string;
  buttonPositive: string;
  buttonNegative?: string;
};

type Rationale = RationaleObject | (() => Promise<boolean>);

type NotificationOption =
  | 'alert'
  | 'badge'
  | 'sound'
  | 'carPlay'
  | 'criticalAlert'
  | 'provisional'
  | 'providesAppSettings';

type NotificationSettings = {
  // unavailable settings will not be included in the response object
  alert?: boolean;
  badge?: boolean;
  sound?: boolean;
  carPlay?: boolean;
  criticalAlert?: boolean;
  provisional?: boolean;
  providesAppSettings?: boolean;
  lockScreen?: boolean;
  notificationCenter?: boolean;
};

type NotificationsResponse = {
  status: PermissionStatus;
  settings: NotificationSettings;
};

type LocationAccuracy = 'full' | 'reduced';
type LocationAccuracyOptions = {purposeKey: string};

Methods

check

Check one permission status.

[!IMPORTANT]
On Android, the check function will never return a blocked status. You need to call request to obtain that information.

function check(permission: Permission): Promise<PermissionStatus>;
check(PERMISSIONS.IOS.CAMERA).then((status) => {
  switch (status) {
    case RESULTS.UNAVAILABLE:
      return console.log('This feature is not available (on this device / in this context)');
    case RESULTS.DENIED:
      return console.log('The permission has not been requested / is denied but requestable');
    case RESULTS.BLOCKED:
      return console.log('The permission is denied and not requestable');
    case RESULTS.GRANTED:
      return console.log('The permission is granted');
    case RESULTS.LIMITED:
      return console.log('The permission is granted but with limitations');
  }
});

request

Request one permission.

The rationale is only available and used on Android. It can be a native alert (a RationaleObject) or a custom implementation (that resolves with a boolean).

function request(permission: Permission, rationale?: Rationale): Promise<PermissionStatus>;
import {request, PERMISSIONS} from 'react-native-permissions';

request(PERMISSIONS.IOS.CAMERA).then((status) => {
  // …
});

checkNotifications

Check notifications permission status and get notifications settings values.

[!IMPORTANT]
On Android 13+, the checkNotifications function will never return a blocked status. You need to call requestNotifications to obtain that information.

function checkNotifications(): Promise<NotificationsResponse>;
import {checkNotifications} from 'react-native-permissions';

checkNotifications().then(({status, settings}) => {
  // …
});

requestNotifications

Request notifications permission status and get notifications settings values.

  • You have to target at least SDK 33 to perform a runtime request on Android 13+.
  • You cannot request notifications permissions on Windows. Disabling / enabling them can only be done through the app settings.

The rationale is only available and used on Android. It can be a native alert (a RationaleObject) or a custom implementation (that resolves with a boolean).

function requestNotifications(
  options?: NotificationOption[], // only used by iOS
  rationale?: Rationale,
): Promise<NotificationsResponse>;
import {requestNotifications} from 'react-native-permissions';

requestNotifications(['alert', 'sound']).then(({status, settings}) => {
  // …
});

checkMultiple

Check multiples permissions in parallel.

[!IMPORTANT]
On Android, the checkMultiple function will never return a blocked status. You need to call requestMultiple to obtain that information.

function checkMultiple<P extends Permission[]>(
  permissions: P,
): Promise<Record<P[number], PermissionStatus>>;
import {checkMultiple, PERMISSIONS} from 'react-native-permissions';

checkMultiple([PERMISSIONS.IOS.CAMERA, PERMISSIONS.IOS.FACE_ID]).then((statuses) => {
  console.log('Camera', statuses[PERMISSIONS.IOS.CAMERA]);
  console.log('FaceID', statuses[PERMISSIONS.IOS.FACE_ID]);
});

requestMultiple

Request multiple permissions in sequence.

function requestMultiple<P extends Permission[]>(
  permissions: P,
): Promise<Record<P[number], PermissionStatus>>;
import {requestMultiple, PERMISSIONS} from 'react-native-permissions';

requestMultiple([PERMISSIONS.IOS.CAMERA, PERMISSIONS.IOS.FACE_ID]).then((statuses) => {
  console.log('Camera', statuses[PERMISSIONS.IOS.CAMERA]);
  console.log('FaceID', statuses[PERMISSIONS.IOS.FACE_ID]);
});

openSettings

Open application / alarms / notifications settings (default to application).

[!NOTE]

  • notifications settings are only available on Android 8+ and iOS 15.4+
  • alarms settings are only available on Android 12+
  • If a choice is not available, it fallbacks to application settings
function openSettings(type?: 'application' | 'alarms' | 'notifications'): Promise<void>;
import {openSettings} from 'react-native-permissions';

openSettings('application').catch(() => console.warn('Cannot open app settings'));

canScheduleExactAlarms (Android)

Check if your app can schedule exact alarms.

function canScheduleExactAlarms(): Promise<boolean>;
import {canScheduleExactAlarms} from 'react-native-permissions';

canScheduleExactAlarms()
  .then((value) => console.log(`Can schedule exact alarms: ${value}`))
  .catch(() => console.warn('Cannot check exact alarms scheduling setting'));

openPhotoPicker (iOS 14+)

Open a picker to update the photo selection when PhotoLibrary permission is limited. This will reject if unsupported or if full permission is already granted.

function openPhotoPicker(): Promise<void>;
import {openPhotoPicker} from 'react-native-permissions';

openPhotoPicker().catch(() => console.warn('Cannot open photo library picker'));

checkLocationAccuracy (iOS 14+)

When LocationAlways or LocationWhenInUse is granted, allow checking if the user share his precise location.

function checkLocationAccuracy(): Promise<LocationAccuracy>;
import {checkLocationAccuracy} from 'react-native-permissions';

checkLocationAccuracy()
  .then((accuracy) => console.log(`Location accuracy is: ${accuracy}`))
  .catch(() => console.warn('Cannot check location accuracy'));

requestLocationAccuracy (iOS 14+)

When LocationAlways or LocationWhenInUse is granted, allow requesting the user for his precise location. Will resolve immediately if full accuracy is already authorized.

function requestLocationAccuracy(options: LocationAccuracyOptions): Promise<LocationAccuracy>;
import {requestLocationAccuracy} from 'react-native-permissions';

requestLocationAccuracy({purposeKey: 'YOUR-PURPOSE-KEY'})
  .then((accuracy) => console.log(`Location accuracy is: ${accuracy}`))
  .catch(() => console.warn('Cannot request location accuracy'));

About iOS LOCATION_ALWAYS permission

On iOS, background location permission can be requested in two different ways (Apple Developer Docs 📘).

Request LOCATION_ALWAYS after LOCATION_WHEN_IN_USE

If the user chooses Allow While Using App when calling request(PERMISSIONS.IOS.LOCATION_WHEN_IN_USE), then calling request(PERMISSIONS.IOS.LOCATION_ALWAYS) afterward will immediately prompt the user:

Location upgrade

| Option | LOCATION_ALWAYS status | LOCATION_WHEN_IN_USE status | | ---------------------- | ------------------------ | ----------------------------- | | Keep Only While Using | RESULTS.BLOCKED | RESULTS.GRANTED | | Change to Always Allow | RESULTS.GRANTED | RESULTS.GRANTED |


Request LOCATION_ALWAYS directly

The user is immediately prompted:

Location first prompt

| Option | LOCATION_ALWAYS status | LOCATION_WHEN_IN_USE status | | --------------------- | ------------------------ | ----------------------------- | | Allow Once | RESULTS.BLOCKED | RESULTS.GRANTED | | Allow While Using App | RESULTS.GRANTED | RESULTS.GRANTED | | Don’t Allow | RESULTS.BLOCKED | RESULTS.BLOCKED |

In this scenario, if the user chooses Allow While Using App, they will see While Using in the app settings and will later be informed that your app is using their location in background with the option to confirm / change it:

Location second prompt

Testing with Jest

If you don't already have a Jest setup file configured, please add the following to your Jest configuration file and create the new jest.setup.js file in project root:

setupFiles: ['<rootDir>/jest.setup.js'];

You can then add the following line to that setup file to mock the NativeModule.RNPermissions:

jest.mock('react-native-permissions', () => require('react-native-permissions/mock'));

Sponsors

This module is provided as is, I work on it in my free time.

If you or your company uses it in a production app, consider sponsoring this project 💰. You also can contact me for premium enterprise support: help with issues, prioritize bugfixes, feature requests, etc.

Sponsors list