page.title=Permissions page.tags=previewresources, androidm page.keywords=permissions, runtime, preview page.image=images/permissions_check.png @jd:body

Quickview

In this document

  1. Overview
  2. Coding for Runtime Permissions
  3. Testing Runtime Permissions
  4. Best Practices and Usage Notes

Video

Google I/O 2015—Android M Permissions: Best Practices for Developers

The M Developer Preview introduces a new app permissions model which streamlines the process for users to install and upgrade apps. If an app running on the M Preview supports the new permissions model, the user does not have to grant any permissions when they install or upgrade the app. Instead, the app requests permissions as it needs them, and the system shows a dialog to the user asking for the permission.

If an app supports the new permissions model, it can still be installed and run on devices running older versions of Android, using the old permissions model on those devices.

Overview

With the M Developer Preview, the platform introduces a new app permissions model. Here's a summary of the key components of this new model:

This permission model changes the way your app behaves for features that require permissions. Here's a summary of the development practices you should follow to adjust to this model:

Note: If an app targets the M Developer Preview, it must use the new permissions model.

As of the launch of the M Developer Preview, not all Google apps fully implement the new permissions model. Google is updating these apps over the course of the M Developer Preview to properly respect Permissions toggle settings.

Note: If your app has its own API surface, do not proxy permissions without first ensuring the caller has the requisite permissions to access that data.

Permission groups

Related permissions are divided into permission groups to allow users to grant related permissions to an app in a single action. The user only has to grant permission once per app for each permission group. If the app subsequently requests a permission from the same permission group, the system automatically grants the permission without any action from the user. The system calls your app's {@link android.app.Activity#onRequestPermissionsResult onRequestPermissionsResult()} method just as if the user had granted permission through the dialog box.

For example, suppose an app lists in its manifest that it needs the SEND_SMS and RECEIVE_SMS permissions, which both belong to android.permission-group.SMS. When the app needs to send a message, it requests the SEND_SMS permission. The system shows the user a dialog box asking if the app can have access to SMS. If the user agrees, the system grants the app the SEND_SMS permission it requested. Later, the app requests RECEIVE_SMS. The system automatically grants this permission, since the user had already approved a permission in the same permission group.

System components and signature permissions

Ordinarily, when the user installs an app, the system only grants the app the permissions listed in the manifest that fall under {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}. However, under some circumstances the system grants the app more permissions:

Forwards and backwards compatibility

If an app does not target the M Developer Preview, the app continues to use the old permissions model even on M Preview devices. When the user installs the app, the system asks the user to grant all permissions listed in the app's manifest.

Note: On devices running the M Developer Preview, a user can turn off permissions for any app (including legacy apps) from the app's Settings screen. If a user turns off permissions for a legacy app, the system silently disables the appropriate functionality. When the app attempts to perform an operation that requires that permission, the operation will not necessarily cause an exception. Instead, it might return an empty data set, signal an error, or otherwise exhibit unexpected behavior. For example, if you query a calendar without permission, the method returns an empty data set.

If you install an app using the new permissions model on a device that is not running the M Preview, the system treats it the same as any other app: the system asks the user to grant all declared permissions at install time.

Note: For the preview release, you must set the minimum SDK version to the M Preview SDK to compile with the preview SDK. This means you will not be able to test such apps on older platforms during the developer preview.

Permissions versus intents

In many cases, you can choose between two ways for your app to perform a task. You can have your app ask for permission to perform the operation itself. Alternatively, you can have the app use an intent to have another app perform the task.

For example, suppose your app needs to be able to take pictures with the device camera. Your app can request the android.permission.CAMERA permission, which allows your app to access the camera directly. Your app would then use the camera APIs to control the camera and take a picture. This approach gives your app full control over the photography process, and lets you incorporate the camera UI into your app.

However, if you don't need such control, you can just use an {@link android.provider.MediaStore#ACTION_IMAGE_CAPTURE ACTION_IMAGE_CAPTURE} intent to request an image. When you start the intent, the user is prompted to choose a camera app (if there isn't already a default camera app), and that app takes the picture. The camera app returns the picture to your app's {@link android.app.Activity#onActivityResult onActivityResult()} method.

Similarly, if you need to make a phone call, access the user's contacts, and so on, you can do that by creating an appropriate intent, or you can request the permission and access the appropriate objects directly. There are advantages and disadvantages to each approach.

If you use permissions:

If you use an intent:

Coding for Runtime Permissions

If your app targets the new M Developer Preview, you must use the new permissions model. This means that in addition to declaring your needed permissions in the manifest, you must also check to see if you have the permissions at run time, and request the permissions if you do not already have them.

Enabling the new permissions model

To enable the new M Developer Preview permissions model, set the app's targetSdkVersion attribute to "MNC", and compileSdkVersion to "android-MNC". Doing so enables all the new permissions features.

For the preview release, you must set minSdkVersion to "MNC" to compile with the preview SDK.

Designating a permission for the M Preview only

You can use the new <uses-permission-sdk-m> element in the app manifest to indicate that a permission is only needed on the M Developer Preview. If you declare a permission this way, then whenever the app is installed on an older device, the system does not prompt the user or grant the permission to the app. By using the <uses-permission-sdk-m> element, you can add new permissions to updated versions of your app without forcing users to grant permissions when they install the update.

If the app is running on a device with the M Developer Preview, <uses-permission-sdk-m> behaves the same as <uses-permission>. The system does not prompt the user to grant any permissions when they install the app, and the app requests permissions as they are needed.

Prompting for permissions

If your app uses the new M Developer Preview permissions model, the user is not asked to grant all permissions when the app is first launched on a device running the M Preview. Instead, your app requests permissions as they are needed. When your app requests a permission, the system shows a dialog to the user.

If your app runs on a device that has SDK 22 or lower, the app uses the old permissions model. When the user installs the app, they are prompted to grant all the permissions your app requests in its manifest, except for those permissions which are labeled with <uses-permission-sdk-m>.

Check what platform the app is running on

This permissions model is only supported on devices running the M Developer Preview. Before calling any of these methods, the app should verify what platform it's running on by checking the value of {@link android.os.Build.VERSION#CODENAME Build.VERSION.CODENAME}. If the device is running the M Developer Preview, {@link android.os.Build.VERSION#CODENAME CODENAME} is "MNC".

Alternatively, you can use the new methods introduced with revision 23 of the v4 and v13 support libraries. The support library methods behave appropriately whether or not the app is running on the M Developer Preview. For more information, see Support library methods for handling permissions.

Check if the app has the needed permission

When the user tries to do something that requires a permission, the app checks to see if it currently has permission to perform this operation. To do this, the app calls {@link android.content.Context#checkSelfPermission checkSelfPermission()}. The app should perform this check even if it knows the user has already granted that permission, since the user can revoke an app's permissions at any time. For example, if a user wants to use an app to take a picture, the app calls Context.checkSelfPermission(Manifest.permission.CAMERA).

Table 1. Permissions and permission groups.

Permission Group Permissions
android.permission-group.CALENDAR
  • android.permission.READ_CALENDAR
  • android.permission.WRITE_CALENDAR
android.permission-group.CAMERA
  • android.permission.CAMERA
android.permission-group.CONTACTS
  • android.permission.READ_CONTACTS
  • android.permission.WRITE_CONTACTS
  • android.permission.GET_ACCOUNTS
android.permission-group.LOCATION
  • android.permission.ACCESS_FINE_LOCATION
  • android.permission.ACCESS_COARSE_LOCATION
android.permission-group.MICROPHONE
  • android.permission.RECORD_AUDIO
android.permission-group.PHONE
  • android.permission.READ_PHONE_STATE
  • android.permission.CALL_PHONE
  • android.permission.READ_CALL_LOG
  • android.permission.WRITE_CALL_LOG
  • com.android.voicemail.permission.ADD_VOICEMAIL
  • android.permission.USE_SIP
  • android.permission.PROCESS_OUTGOING_CALLS
android.permission-group.SENSORS
  • android.permission.BODY_SENSORS
android.permission-group.SMS
  • android.permission.SEND_SMS
  • android.permission.RECEIVE_SMS
  • android.permission.READ_SMS
  • android.permission.RECEIVE_WAP_PUSH
  • android.permission.RECEIVE_MMS
  • android.permission.READ_CELL_BROADCASTS
android.permission-group.STORAGE
  • android.permission.READ_EXTERNAL_STORAGE
  • android.permission.WRITE_EXTERNAL_STORAGE

Explain why the app needs permissions

In some circumstances, you might want to help the user understand why your app needs a permission. For example, if a user launches a photography app, the user probably won't be surprised that the app asks for permission to use the camera. But if the user turns down that permission request, then launches the photography app again, that might indicate that the user needs some help understanding why the permission is needed.

To help find the situations where you need to provide extra explanation, the system provides the {@link android.app.Activity#shouldShowRequestPermissionRationale shouldShowRequestPermissionRationale()} method. This method returns true if the app has requested this permission previously and the user denied the request. That indicates that you should probably explain to the user why you need the permission.

If the user turned down the permission request in the past and chose the Don't ask again option in the permission request system dialog, this method returns false. The method also returns false if the device policy prohibits the app from having that permission.

Request permissions if necessary

If the app doesn't already have the permission it needs, the app calls the {@link android.app.Activity#requestPermissions requestPermissions()} method to request the appropriate permission or permissions. The app passes the permission or permissions it wants, and also an integer "request code". This method functions asynchronously: it returns right away, and after the user responds to the dialog box, the system calls the app's callback method with the results, passing the same "request code" that the app passed to {@link android.app.Activity#requestPermissions requestPermissions()}.

The following code code checks if the app has permission to read the user's contacts, and requests the permission if necessary:

if (checkSelfPermission(Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (shouldShowRequestPermissionRationale(
            Manifest.permission.READ_CONTACTS)) {
        // Explain to the user why we need to read the contacts
    }

    requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

    // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
    // app-defined int constant

    return;
}

Note: When your app calls the framework's {@link android.app.Activity#requestPermissions requestPermissions()} method, the system shows a standard dialog box to the user. Your app cannot configure or alter that dialog box. If you need to provide any information or explanation to the user, you should do that before you call {@link android.app.Activity#requestPermissions requestPermissions()}, as described in Explain why the app needs permissions.

Handle the permissions request response

When an app requests permissions, the system presents a dialog box to the user. When the user responds, the system invokes your app's {@link android.app.Activity#onRequestPermissionsResult} passing it the user response. Your app needs to override that method. The callback is passed the same request code you passed to {@link android.app.Activity#requestPermissions requestPermissions()}. For example, if an app requests READ_CONTACTS access it might have the following callback method:

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! do the
                // calendar task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'switch' lines to check for other
        // permissions this app might request
    }
}

If the user denies a permission request, your app should take appropriate action. For example, your app might show a dialog explaining why it could not perform the user's original request.

When the system asks the user to grant a permission, the user has the option of telling the system not to ask for that permission again. In that case, when an app uses {@link android.app.Activity#requestPermissions requestPermissions()} to ask for that permission, the system immediately denies the request. In this case, the system calls your {@link android.app.Activity#onRequestPermissionsResult onRequestPermissionsResult()} the same way it would if the user had explicitly rejected your request again. For this reason, your app cannot assume that any direct interaction with the user has taken place.

Testing Runtime Permissions

If your app targets the M Developer Preview, you must test that it handles permissions properly. You cannot assume that your app has any particular permissions when it runs. When the app is first launched, it is likely to have no permissions, and the user can revoke or restore permissions at any time.

You should test your app to make sure it behaves properly under all permission situations. With the M Preview SDK, we have provided new Android Debug Bridge (adb) commands to enable you to test your app with whatever permissions settings you need to try.

New adb commands and options

The M Preview SDK Platform-tools provides several new commands to let you test how your app handles permissions.

Install with permissions

You can use the adb install command's new -g option, which installs the app and grants all permissions listed in its manifest:

$ adb install -g <path_to_apk>

Grant and revoke permissions

You can use new ADB package manager (pm) commands to grant and revoke permissions to an installed app. This functionality can be useful for automated testing.

To grant a permission, use the package manager's grant command:

$ adb pm grant <package_name> <permission_name>

For example, to grant the com.example.myapp package permission to record audio, use this command:

$ adb pm grant com.example.myapp android.permission.RECORD_AUDIO

To revoke a permission, use the package manager's revoke command:

$ adb pm revoke <package_name> <permission_name>

Best Practices and Usage Notes

The new permissions model gives users a smoother experience, and makes it easier for them to install apps and feel comfortable with what the apps are doing. We recommend the following best practices to take full advantage of the new model.

Only ask for permissions you need

Every time you ask for a permission, you force the user to make a decision. If the user turns down the request, that reduces your app's functionality. You should minimize the number of times you make these requests.

For example, quite often your app can get needed functionality by using an intent instead of asking for permissions. If your app needs to take pictures with the phone's camera, your app can use a {@link android.provider.MediaStore#ACTION_IMAGE_CAPTURE MediaStore.ACTION_IMAGE_CAPTURE} intent. When your app executes the intent, the system prompts the user to choose an already-installed camera app to take the picture.

Don't overwhelm the user

If you confront the user with a lot of requests for permissions at once, you may overwhelm the user and cause them to quit your app. Instead, you should ask for permissions as you need them.

In some cases, one or more permissions might be absolutely essential to your app. In that case, it might make sense to ask for all the permissions as soon as the app launches. For example, if you make a photography app, the app would need access to the device camera. When the user launches the app for the first time, they won't be surprised to be asked for permission to use the camera. But if the same app also had a feature to share photos with the user's contacts, you probably should not ask for that permission at first launch. Instead, wait until the user tries to use the "sharing" feature and ask for the permission then.

If your app provides a tutorial, it may make sense to request the app's essential permissions at the end of the tutorial sequence.

Explain why you need permissions

The permissions dialog shown by the system when you call {@link android.app.Activity#requestPermissions requestPermissions()} says what permission your app wants, but doesn't say why. In some cases, the user may find that puzzling. It's a good idea to explain to the user why your app wants the permissions before calling {@link android.app.Activity#requestPermissions requestPermissions()}.

For example, a photography app might want to use location services, so it can geotag the photos. A typical user might not understand that a photo can contain location information, and would be puzzled why their photography app wanted to know the location. So in this case, it's a good idea for the app to tell the user about this feature before calling {@link android.app.Activity#requestPermissions requestPermissions()}.

One way to do this is to incorporate these requests into an app tutorial. The tutorial can show each of the app's features in turn, and as it does this, it can explain what permissions are needed. For example, the photography app's tutorial can demonstrate its "share photos with your contacts" feature, then tell the user that they need to give permission for the app to see the user's contacts. The app can then call {@link android.app.Activity#requestPermissions requestPermissions()} to ask the user for that access. Of course, not every user is going to follow the tutorial, so you still need to check for and request permissions during the app's normal operation.

Support library methods for handling permissions

Revision 23 of the v4 and v13 support libraries provide several new methods for managing permissions. The support library methods work properly on any device that can use those libraries. Thus, if you use the support library methods, you do not need to check whether your app is running on a device with the M Developer Preview. If an app is installed on a device running the M Preview, the support library methods behave the same as their framework equivalents. If the device is running an earlier version of Android, the methods behave appropriately, as described below.

The v4 support library provides the following permissions methods:

{@link android.support.v4.content.ContextCompat#checkSelfPermission ContextCompat.checkSelfPermission()}
Returns true if the app has the specified permission, whether or not the device is using the M Preview.
{@link android.support.v4.app.ActivityCompat#requestPermissions ActivityCompat.requestPermissions()}
If the device is not running the M Preview, invokes the callback method in {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}. Passes {@link android.content.pm.PackageManager#PERMISSION_GRANTED PERMISSION_GRANTED} if the app already has the specified permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED PERMISSION_DENIED} if it does not.
{@link android.support.v4.app.ActivityCompat#shouldShowRequestPermissionRationale ActivityCompat.shouldShowRequestPermissionRationale()}
If the device is not running the M Preview, always returns false.

The v4 support library also contains the {@link android.support.v4.content.PermissionChecker} class, which provides several static utility methods for apps that use IPC to provide services for other apps. For example, {@link android.support.v4.content.PermissionChecker#checkCallingPermission PermissionChecker.checkCallingPermission()} checks whether an IPC made by a particular package has a specified permission.

Note: If your app acts on behalf of third-party apps to call platform methods that require runtime permissions on behalf of a third-party app, you should use the appropriate {@link android.support.v4.content.PermissionChecker} methods to ensure that the other app is allowed to perform the operation. The platform has a compatibility mode that allows users to revoke a legacy app's access to permission-protected methods. If the user revokes access in compatibility mode the app's permissions are not actually revoked; instead, access to the APIs is restricted. The {@link android.support.v4.content.PermissionChecker} methods verify app permissions in both normal and legacy modes.

The v13 support library provides the following permissions methods:

{@link android.support.v13.app.FragmentCompat#requestPermissions FragmentCompat.requestPermissions()}
If the device is not running the M Preview, invokes the callback method in FragmentCompat.OnRequestPermissionsResultCallback. Passes {@link android.content.pm.PackageManager#PERMISSION_GRANTED PERMISSION_GRANTED} if the app already has the specified permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED PERMISSION_DENIED} if it does not.
{@link android.support.v13.app.FragmentCompat#shouldShowRequestPermissionRationale FragmentCompat.shouldShowRequestPermissionRationale()}
If the device is not running the M Preview, always returns false.

Normal permissions

Many permissions are designated as {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}, which indicates that there's no great risk to the user's privacy or security in letting apps have those permissions. For example, users would reasonably want to know whether an app can read their contact information, so users have to grant this permission explicitly. By contrast, there's no great risk in allowing an app to vibrate the device, so that permission is designated as normal.

If an app declares in its manifest that it needs a normal permission, the system automatically grants the app that permission at install time. The system does not prompt the user to grant normal permissions, and users cannot revoke these permissions.

If your app declares that it needs normal permissions, the app does not need to call {@link android.content.Context#checkSelfPermission checkSelfPermission()} or {@link android.app.Activity#requestPermissions requestPermissions()} for those permissions. Since you declared the permissions in the manifest, you can be sure your app was granted those permissions at install time.

Currently, the following permissions are classified as {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}: