Handling Requesting for Permissions Like a Pro in Flutter
Tags: flutter, beginners, ios, android
Published: 2019-09-14 15:17:38

In this lesson, we are going to look at how to request and check permissions on Android and IOS in Flutter.

## Package(s)

- Permission Handler ([permission_handler](https://pub.dev/packages/permission_handler))

### Installation

The process of installing a flutter package is quite simple, just open the **pubspec** file and add the package into your dependency bloc section.

```yaml
dependencies:
  permission_handler:
```

> **TIP:** You can use caret versioning to restrict the package version to a specific major version. For instance, `permission_handler: ^3.0.0` restricts it to version 3, but you will get both minor updates and patches.
> You can learn more about how dart pub package manager works [here](https://codinglatte.com/posts/flutter/flutter-a-closer-look-at-how-pub-handles-dependency-versions/) if you are interested.

## Permissions

First, we need to determine which permissions we need, because your app needs to publicly declare the permissions it needs. Some less-sensitive permissions such as the internet, etc. are granted automatically. While other more sensitive permissions, think of Location, Contacts, etc. require user authorization before your app can use them.

### iOS permissions

In iOS, this done by adding the permissions to **Information Property List File** i.e. `info.plist`, with the Permission you need being the Key, accompanied by the reason why your app needs to use the feature.

```xml
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires to save your images user gallery</string>
```

In Flutters’ case, the `info.plist` in the `iOS/Runner` directory at the root of your project. You can learn more about the `info.plist` [here](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Introduction/Introduction.html).

You can find the complete list of permissions [here](https://www.iosdev.recipes/info-plist/permissions/) and guidelines for asking permission on iOS [here](https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/requesting-permission/).

### Android permissions

In Android, you can achieve the same by adding the `<uses-permission>` tag to the android manifest, this in the `android/src/main/AndroidManifest.xml` directory.

```xml
<manifest ...>
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <application ...>
        ...
    </application>
</manifest>
```

You can learn more about permission on Android [here](https://developer.android.com/training/permissions/requesting) and the best practices [here](https://developer.android.com/training/permissions/usage-notes).

## Requesting for Permission

To request permission, first you need to import the package:

```dart
import 'package:permission_handler/permission_handler.dart';
```

And then, let say you want to request contact permission, you can do it like this. You pass a list of permissions you are requesting for, which allows you to ask for multiple permissions you need at once.

```dart
final PermissionHandler _permissionHandler = PermissionHandler();
var result = await _permissionHandler.requestPermissions([PermissionGroup.contacts]);
```

And finally, you can inspect the result to see if the user granted permission or not. The results object is an array of `PermissionStatus`. The key of the array is the permission you were asking.

The possible permission statuses are:

| Status                    | Why                                                                                       |
| ------------------------- | ----------------------------------------------------------------------------------------- |
| **Granted**               | Your app has been given permission to use the feature in question                         |
| **Denied**                | Your app has been given permission to use the feature in question                         |
| **Disabled**              | Feature in question is disabled i.e. when the Location feature is disabled.               |
| **Restricted** (iOS only) | OS has restricted access to a specific feature due to something like   parental controls. |
| **Unknown**               | Unknown state of permissions.                                                             |

For instance, in our example above, we can check if permission to access contacts was granted like this:

```dart
if (result[PermissionGroup.contacts] == PermissionStatus.granted) {
  // permission was granted
}
```

You can also use a switch statement to react to the results of your request.

```dart
switch (result[PermissionGroup.contacts]) {
  case PermissionStatus.granted:
    // do something
    break;
  case PermissionStatus.denied:
    // do something
    break;
  case PermissionStatus.disabled:
    // do something
    break;
  case PermissionStatus.restricted:
    // do something
    break;
  case PermissionStatus. Unknown:
    // do something
    break;
  default:
}
```

## Checking if your App has been Given Permission

It is important that your app can check if it has permission to access certain features. This allows your app to decide based on if the user has granted permission or not. On top of that, it can help you determine if a feature is available or disabled on the users' device.

You can check for permission by using the `checkPermissionStatus` function, which accepts the Permission as a parameter.

```dart
final PermissionHandler _permissionHandler = PermissionHandler();

var permissionStatus = await _permissionHandler.checkPermissionStatus(PermissionGroup.location);
```

This returns a `PermissionStatus` class – we saw it above – which details the status of the permission.

```dart
switch (permissionStatus) {
  case PermissionStatus.granted:
    // do something
    break;
  case PermissionStatus.denied:
    // do something
    break;
  case PermissionStatus.disabled:
    // do something
    break;
  case PermissionStatus.restricted:
    // do something
    break;
  case PermissionStatus.unknown:
    // do something
    break;
  default:
}
```

## Tip

Some permissions such as contacts, calendar, microphone, location, etc. are common across iOS and Android. On the other hand, there are some permissions that either do not match up on both OSs. While others are just on one OS, i.e. storage, SMS, phone, etc. are only on android. You might want to determine which platform it is before requesting permission from the user.

Take a camera app, for instance, if you wanted photos to appear in the gallery, on iOS, you need photos permission while in android you need external storage permission.

```dart
var permission = Platform.isAndroid ? PermissionGroup.storage : PermissionGroup.photos;
```

And then, you can check if the user has granted your app permission:

```dart
await _permissionHandler.checkPermissionStatus(permission);
```

Or request for permission:

```dart
await _permissionHandler.requestPermissions([permission]);
```

## Resources

- Requesting for Permission on IOS – [Link](https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/requesting-permission/).
- Requesting for Permission on Android – [Link](https://developer.android.com/training/permissions/requesting).
- Permission Best Practices on Android – [Link](https://developer.android.com/training/permissions/usage-notes).
- About Information Property List Files – [Link](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html).
- Android App Manifest – [Link](https://developer.android.com/guide/topics/manifest/manifest-intro).