permission_plus 1.0.0 copy "permission_plus: ^1.0.0" to clipboard
permission_plus: ^1.0.0 copied to clipboard

A Flutter plugin for requesting and checking permissions.

permission_plus #

A unified, cross-platform Flutter plugin for requesting and checking permissions on Android, iOS, macOS, Web, Windows, and Linux.

Features #

  • Check permission status (granted, denied, restricted, permanentlyDenied, limited, provisional, and notDetermined).
  • Request a single permission or multiple permissions at once.
  • Open the platform's app settings page.
  • Determine if a rationale should be shown before requesting a permission (Android only).
  • Fetch location accuracy (precise vs reduced).
  • Type-safe implementation leveraging Pigeon-generated host APIs.

Supported Platforms #

  • Android: API 21+
  • iOS: iOS 12.0+
  • macOS: macOS 11.0+
  • Web: Chrome, Firefox, Safari (uses the Web Permissions API)
  • Windows: Windows 10+ (Win32 / WinRT)
  • Linux: Any modern Linux distribution (returns granted for desktop apps)

Setup #

Android #

Add the required permissions to your android/app/src/main/AndroidManifest.xml file. Only add the permissions your app actually uses:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Camera -->
    <uses-permission android:name="android.permission.CAMERA" />

    <!-- Microphone / Audio -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <!-- Location -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

    <!-- Contacts -->
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />

    <!-- Calendar -->
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />

    <!-- Storage / Photos -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <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_AUDIO" />

    <!-- Bluetooth -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Sensors / Motion -->
    <uses-permission android:name="android.permission.BODY_SENSORS" />
    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

    <!-- Phone -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CALL_PHONE" />

    <!-- SMS -->
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />
</manifest>

iOS #

Add the corresponding usage descriptions to your ios/Runner/Info.plist. Only add the keys for permissions your app actually requests:

<key>NSCameraUsageDescription</key>
<string>This app needs camera access to take photos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access to record audio.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access to select photos.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs photo library addition access to save photos.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to find nearby places.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs location always access to track background location.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs location access for map features.</string>
<key>NSContactsUsageDescription</key>
<string>This app needs contacts access to find friends.</string>
<key>NSCalendarsUsageDescription</key>
<string>This app needs calendar access to schedule events.</string>
<key>NSRemindersUsageDescription</key>
<string>This app needs reminders access to create tasks.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app needs bluetooth access to connect to devices.</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app needs bluetooth access to connect to devices in background.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app needs speech recognition access for voice commands.</string>
<key>NSAppleMusicUsageDescription</key>
<string>This app needs media library access to play music.</string>
<key>NSMotionUsageDescription</key>
<string>This app needs motion access to track steps.</string>
<key>NSUserTrackingUsageDescription</key>
<string>This app needs tracking access for personalized ads.</string>

macOS #

Add the corresponding usage descriptions to your macos/Runner/Info.plist. Only add the keys for permissions your app actually requests:

<key>NSCameraUsageDescription</key>
<string>This app needs camera access to take photos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access to record audio.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access to select photos.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to find nearby places.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs location always access to track background location.</string>
<key>NSContactsUsageDescription</key>
<string>This app needs contacts access to find friends.</string>
<key>NSCalendarsUsageDescription</key>
<string>This app needs calendar access to schedule events.</string>
<key>NSRemindersUsageDescription</key>
<string>This app needs reminders access to create tasks.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app needs bluetooth access to connect to devices.</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app needs bluetooth access to connect to devices in background.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app needs speech recognition access for voice commands.</string>
<key>NSAppleMusicUsageDescription</key>
<string>This app needs media library access to play music.</string>
<key>NSUserNotificationsUsageDescription</key>
<string>This app needs notification access to send alerts.</string>

Additionally, if your macOS app is sandboxed (which is the default), you must add entitlements to macos/Runner/DebugProfile.entitlements and Release.entitlements. Only add entitlements for resources you use:

<!-- Hardware Access -->
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.bluetooth</key>
<true/>

<!-- Network Access (Required for Speech Recognition) -->
<key>com.apple.security.network.client</key>
<true/>

<!-- Personal Information -->
<key>com.apple.security.personal-information.location</key>
<true/>
<key>com.apple.security.personal-information.addressbook</key>
<true/>
<key>com.apple.security.personal-information.calendars</key>
<true/>
<key>com.apple.security.personal-information.photos-library</key>
<true/>

Important Note for macOS Notifications: macOS UNUserNotificationCenter enforces strict security for notifications. If you are developing locally and your app is "Ad-hoc" signed (flutter run without an Apple Developer account configured in Xcode), macOS will instantly reject notification requests and return permanentlyDenied without showing a prompt. To test macOS notification prompts natively, you must open macos/Runner.xcworkspace in Xcode and sign the app with a valid Apple Developer Team, OR you can test notification logic using the iOS Simulator (which bypasses this signing restriction).

Web, Windows, and Linux #

No special setup is required.

  • On the Web, the browser handles permission prompts automatically using the standard Web Permissions API.
  • On Windows, Win32 apps have unrestricted access to most resources. Permissions like Camera and Location will check Windows Privacy Settings.
  • On Linux, standard desktop applications have unrestricted access to the user's hardware and files, so all permissions will return granted.

Usage #

1. Check a permission status #

import 'package:permission_plus/permission_plus.dart';

Future<void> checkCamera() async {
  final status = await PermissionPlus.checkPermission(PermissionType.camera);
  
  switch (status) {
    case PermissionStatus.granted:
      print('Camera access is granted.');
      break;
    case PermissionStatus.denied:
      print('Camera access is denied.');
      break;
    case PermissionStatus.permanentlyDenied:
      print('Camera access is permanently denied.');
      break;
    case PermissionStatus.restricted:
      print('Camera access is restricted (e.g. parental controls).');
      break;
    case PermissionStatus.limited:
      print('Camera access is limited.');
      break;
    case PermissionStatus.provisional:
      print('Camera access is provisional.');
      break;
    case PermissionStatus.notDetermined:
      print('Camera access has not been determined yet.');
      break;
  }
}

2. Request a permission #

import 'package:permission_plus/permission_plus.dart';

Future<void> requestCamera() async {
  final status = await PermissionPlus.requestPermission(PermissionType.camera);
  if (status == PermissionStatus.granted) {
    print('Camera permission granted');
  } else if (status == PermissionStatus.permanentlyDenied) {
    print('Permission permanently denied. Please enable it in settings.');
    await PermissionPlus.openSettings();
  }
}

3. Request multiple permissions #

import 'package:permission_plus/permission_plus.dart';

Future<void> requestMultiple() async {
  final statuses = await PermissionPlus.requestPermissions([
    PermissionType.camera,
    PermissionType.location,
  ]);

  if (statuses[PermissionType.camera] == PermissionStatus.granted) {
    print('Camera granted');
  }
}

4. Open App Settings #

If a permission is permanentlyDenied, you can guide the user to the platform's settings page so they can enable it manually.

import 'package:permission_plus/permission_plus.dart';

Future<void> openSettings() async {
  final opened = await PermissionPlus.openSettings();
  if (opened) {
    print('Successfully opened settings.');
  } else {
    print('Could not open settings.');
  }
}

Contributing #

Contributions are welcome! Please open an issue or pull request on the GitHub repository.