How to handle permissions in Flutter

Flutter Aug 4, 2023

Managing permissions is an important part of developing mobile applications. It ensures that applications can use necessary device features while also respecting user privacy. In this post, we will explore how to effectively manage permissions in Flutter using the permission_handler package. We will cover the installation process, configuration for Android and iOS platforms, and the implementation of permission requests. By the end of this post, you will have the knowledge and tools to handle permissions in your Flutter applications.

Installing

To get started, we need to install the permission_handler package into our project. The installation process is simple. Just execute the following command: flutter pub add permission_handler.

Once the command is executed, make sure to check your pubspec.yaml file for the added dependencies. You should see the permission_handler package included in the dependencies section, like this:

dependencies:
  flutter:
    sdk: flutter
  permission_handler: ^10.4.3

Android

In Android, to access specific permissions, you need to add an entry in the AndroidManifest.xml file. For example, to access the location, you would add the following code:

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

You can find documentation for all the permissions in Android here.

Additionally, make sure to check your android/gradle.properties file and ensure it contains the following entries:

android.useAndroidX=true
android.enableJetifier=true

At last, set the compileSdkVersion in your android/app/build.gradle file to 33:

android {
    namespace "com.example.codeonwards_demo"
    compileSdkVersion 33
    ...
}

iOS

In iOS, you need to add the location permission to the ios/Runner/info.plist file. Here is an example of how to add permission for the location:

<plist version="1.0">
    <dict>
        <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
        <string>This application needs access to the location</string>
        ...
    </dict>
</plist>

Ensure that the key between the <key> tags remains exactly the same. However, feel free to modify the description between the <string> tags. This description will be displayed to the user when requesting location access.

Unfortunately, I do not have access to an iOS device for testing, so I recommend checking the package's documentation if you run into issues on iOS devices.

Asking location permissions

In the code snippet below we will create a simple Flutter application that demonstrates how to use the permission_handler package to request location permissions. It consists out of two classes: MyApp and HomePage.

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  void _requestLocationPermission(BuildContext context) async {
    PermissionStatus status = await Permission.location.request();

    switch (status) {
      case PermissionStatus.granted:
        _showSnackBar(context, 'Permission granted', Colors.green);
      case PermissionStatus.denied:
        _showSnackBar(context, 'Permission denied', Colors.amber);
      case PermissionStatus.permanentlyDenied:
        _showSnackBar(context, 'Permanently denied', Colors.redAccent);
      default:
        _showSnackBar(context, 'Something went wrong', Colors.red);
    }
  }

  void _showSnackBar(BuildContext context, String text, Color color) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text(text, textAlign: TextAlign.center),
      backgroundColor: color,
    ));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Requesting Permission Example'),
      ),
      body: Center(
        child: ElevatedButton(
          style: ElevatedButton.styleFrom(minimumSize: Size(200, 50)),
          onPressed: () => _requestLocationPermission(context),
          child: Text(
            'Request Location Permission',
            style: TextStyle(fontSize: 20),
          ),
        ),
      ),
    );
  }
}

In this code snippet, the MyApp widget, returns a MaterialApp which has the HomePage set as the initial home page. The HomePage class contains a Scaffold widget and a centered ElevatedButton with the text "Request Location Permission".

When the button is pressed, the _requestLocationPermission function is called. This function is responsible for requesting location permissions using the permission_handler package. It uses the await keyword to wait for the permission request to complete and stores the result in a variable called status, which is of type PermissionStatus.

Based on the permission status, the application shows a SnackBar widget at the bottom of the screen using the _showSnackBar function. The SnackBar provides feedback to the user with different colors and messages depending on the permission status. For example, if the location permission is granted, an informative green SnackBar widget displays "Permission granted

flutter_requesting_location_permission

User's device settings

To improve our application's functionality, we can use the openAppSettings function, which allows users to access the application's permissions settings directly. This way, if a user for example, accidentally denies permission, clicking on the button will open the settings, providing them with the opportunity to review and modify their decision.

void _requestLocationPermission(BuildContext context) async {
  PermissionStatus status = await Permission.location.request();

  switch (status) {
    case PermissionStatus.granted:
      _showSnackBar(context, 'Permission granted', Colors.green);
    case PermissionStatus.denied:
      _showSnackBar(context, 'Permission denied', Colors.amber);
      openAppSettings();
    case PermissionStatus.permanentlyDenied:
      _showSnackBar(context, 'Permanently denied', Colors.redAccent);
      openAppSettings();
    default:
      _showSnackBar(context, 'Something went wrong', Colors.red);
  }
}

In the updated _requestLocationPermission function, we have modified the denied cases to call the openAppSettings function. Now, when the user denies permission, the app will automatically open the device's settings, offering users to adjust their permission preferences.

flutter_open_device_settings_to_set_permissions

Conclusion

In this post, we have explored how to handle permissions in Flutter using the permission_handler package. We started by installing the package and configuring permissions for both Android and iOS platforms. The implementation of the permission request was demonstrated through a simple application that requests location permissions when a button is pressed. With this knowledge, you can now effectively manage permissions in your Flutter applications.

Tags