On most operating systems, permissions aren't just granted to apps at install time. Rather, developers have to ask the user for permissions while the app is running.
This plugin provides a cross-platform (iOS, Android) API to request permissions and check their status. You can also open the device's app settings so users can grant a permission.
On Android, you can show a rationale for requesting a permission.
See the FAQ section for more information on common questions when using the permission_handler plugin.
While the permissions are being requested during runtime, you'll still need to tell the OS which permissions your app might potentially use. That requires adding permission configuration to Android- and iOS-specific files.
Android
iOS
There are a number of Permission
s. You can get a Permission
's status
, which is either granted
, denied
, restricted
, permanentlyDenied
, limited
, or provisional
.
var status = await Permission.camera.status;
if (status.isDenied) {
// We didn't ask for permission yet or the permission has been denied before but not permanently.
}
// You can can also directly ask the permission about its status.
if (await Permission.location.isRestricted) {
// The OS restricts access, for example because of parental controls.
}
Call request()
on a Permission
to request it. If it has already been granted before, nothing happens.request()
returns the new status of the Permission
.
if (await Permission.contacts.request().isGranted) {
// Either the permission was already granted before or the user just granted it.
}
// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
Permission.storage,
].request();
print(statuses[Permission.location]);
Some permissions, for example location or acceleration sensor permissions, have an associated service, which can be enabled
or disabled
.
if (await Permission.locationWhenInUse.serviceStatus.isEnabled) {
// Use location.
}
You can also open the app settings:
if (await Permission.speech.isPermanentlyDenied) {
// The user opted to never again see the permission request dialog for this
// app. The only way to change the permission's status now is to let the
// user manually enable it in the system settings.
openAppSettings();
}
On Android, you can show a rationale for using a permission:
bool isShown = await Permission.contacts.shouldShowRequestRationale;
Some permissions will not show a dialog asking the user to allow or deny the requested permission.
This is because the OS setting(s) of the app are being retrieved for the corresponding permission.
The status of the setting will determine whether the permission is granted
or denied
.
The following permissions will show no dialog:
The following permissions will show no dialog, but will open the corresponding setting intent for the user to change the permission status:
The locationAlways
permission can not be requested directly, the user has to request the locationWhenInUse
permission first. Accepting this permission by clicking on the 'Allow While Using App' gives the user the possibility to request the locationAlways
permission. This will then bring up another permission popup asking you to Keep Only While Using
or to Change To Always Allow
.
On Android the Permission.storage
permission is linked to the Android READ_EXTERNAL_STORAGE
and WRITE_EXTERNAL_STORAGE
permissions. Starting from Android SDK 29 (Android 10) the READ_EXTERNAL_STORAGE
and WRITE_EXTERNAL_STORAGE
permissions have been marked deprecated and have been fully removed/ disabled since Android SDK 33 (Android 13).
If your application needs access to media files Google recommends using the READ_MEDIA_IMAGES
, READ_MEDIA_VIDEOS
or READ_MEDIA_AUDIO
permissions instead. These can be requested using the Permission.photos
, Permission.videos
and Permission.audio
respectively. To request these permissions make sure the compileSdkVersion
in the android/app/build.gradle
file is set to 33
.
If your application needs access to Androids file system it is possible to request the MANAGE_EXTERNAL_STORAGE
permission (using Permission.manageExternalStorage
). As of Android SDK 30 (Android 11) the MANAGE_EXTERNAL_STORAGE
permission is considered a high-risk or sensitive permission. There for it is required to declare the use of these permissions if you intend to release the application via the Google Play Store.
Please file any issues, bugs or feature request as an issue on our GitHub page. Commercial support is available if you need help with integration with your app or services. You can contact us at hello@baseflow.com.
If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our contribution guide and send us your pull request.
This Permission handler plugin for Flutter is developed by Baseflow. You can contact us at hello@baseflow.com
Run this command:
With Flutter:
$ flutter pub add permission_handler
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
permission_handler: ^10.4.3
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:permission_handler/permission_handler.dart';
import 'dart:io';
import 'package:baseflow_plugin_template/baseflow_plugin_template.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
runApp(BaseflowPluginExample(
pluginName: 'Permission Handler',
githubURL: 'https://github.com/Baseflow/flutter-permission-handler',
pubDevURL: 'https://pub.dev/packages/permission_handler',
pages: [PermissionHandlerWidget.createPage()]));
}
///Defines the main theme color
final MaterialColor themeMaterialColor =
BaseflowPluginExample.createMaterialColor(
const Color.fromRGBO(48, 49, 60, 1));
/// A Flutter application demonstrating the functionality of this plugin
class PermissionHandlerWidget extends StatefulWidget {
/// Create a page containing the functionality of this plugin
static ExamplePage createPage() {
return ExamplePage(
Icons.location_on, (context) => PermissionHandlerWidget());
}
@override
_PermissionHandlerWidgetState createState() =>
_PermissionHandlerWidgetState();
}
class _PermissionHandlerWidgetState extends State<PermissionHandlerWidget> {
@override
Widget build(BuildContext context) {
return Center(
child: ListView(
children: Permission.values
.where((permission) {
if (Platform.isIOS) {
return permission != Permission.unknown &&
permission != Permission.phone &&
permission != Permission.sms &&
permission != Permission.ignoreBatteryOptimizations &&
permission != Permission.accessMediaLocation &&
permission != Permission.activityRecognition &&
permission != Permission.manageExternalStorage &&
permission != Permission.systemAlertWindow &&
permission != Permission.requestInstallPackages &&
permission != Permission.accessNotificationPolicy &&
permission != Permission.bluetoothScan &&
permission != Permission.bluetoothAdvertise &&
permission != Permission.bluetoothConnect &&
permission != Permission.nearbyWifiDevices &&
permission != Permission.videos &&
permission != Permission.audio &&
permission != Permission.scheduleExactAlarm &&
permission != Permission.sensorsAlways;
} else {
return permission != Permission.unknown &&
permission != Permission.mediaLibrary &&
permission != Permission.photosAddOnly &&
permission != Permission.reminders &&
permission != Permission.bluetooth &&
permission != Permission.appTrackingTransparency &&
permission != Permission.criticalAlerts;
}
})
.map((permission) => PermissionWidget(permission))
.toList()),
);
}
}
/// Permission widget containing information about the passed [Permission]
class PermissionWidget extends StatefulWidget {
/// Constructs a [PermissionWidget] for the supplied [Permission]
const PermissionWidget(this._permission);
final Permission _permission;
@override
_PermissionState createState() => _PermissionState(_permission);
}
class _PermissionState extends State<PermissionWidget> {
_PermissionState(this._permission);
final Permission _permission;
PermissionStatus _permissionStatus = PermissionStatus.denied;
@override
void initState() {
super.initState();
_listenForPermissionStatus();
}
void _listenForPermissionStatus() async {
final status = await _permission.status;
setState(() => _permissionStatus = status);
}
Color getPermissionColor() {
switch (_permissionStatus) {
case PermissionStatus.denied:
return Colors.red;
case PermissionStatus.granted:
return Colors.green;
case PermissionStatus.limited:
return Colors.orange;
default:
return Colors.grey;
}
}
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(
_permission.toString(),
style: Theme.of(context).textTheme.bodyLarge,
),
subtitle: Text(
_permissionStatus.toString(),
style: TextStyle(color: getPermissionColor()),
),
trailing: (_permission is PermissionWithService)
? IconButton(
icon: const Icon(
Icons.info,
color: Colors.white,
),
onPressed: () {
checkServiceStatus(
context, _permission as PermissionWithService);
})
: null,
onTap: () {
requestPermission(_permission);
},
);
}
void checkServiceStatus(
BuildContext context, PermissionWithService permission) async {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text((await permission.serviceStatus).toString()),
));
}
Future<void> requestPermission(Permission permission) async {
final status = await permission.request();
setState(() {
print(status);
_permissionStatus = status;
print(_permissionStatus);
});
}
}
Download details:
Author: baseflow
Source: https://github.com/baseflow/flutter-permission-handler