Google is committed to advancing racial equity for Black communities. See how.

Request app permissions

Every Android app runs in a limited-access sandbox. If your app needs to use resources or information outside of its own sandbox, you can declare a permission and set up a permission request that provides this access. These steps are part of the workflow for using permissions.

If you declare any dangerous permissions, and if your app is installed on a device that runs Android 6.0 (API level 23) or higher, you must request the dangerous permissions at runtime by following the steps in this guide.

If you don't declare any dangerous permissions, or if your app is installed on a device that runs Android 5.1 (API level 22) or lower, the permissions are automatically granted, and you don't need to complete any of the remaining steps on this page.

Basic principles

The basic principles for requesting permissions at runtime are as follows:

  • Ask for permissions in context, when the user starts to interact with the feature that requires it.
  • Don't block the user. Always provide the option to cancel an educational UI flow related to permissions.
  • If the user denies or revokes a permission that a feature needs, gracefully degrade your app so that the user can continue using your app, possibly by disabling the feature that requires the permission.
  • Don't assume any system behavior.

Check for permissions

If your app needs a dangerous permission, you must check whether you have that permission every time you perform an operation that requires that permission. On Android 6.0 (API level 23) and higher, users can revoke dangerous permissions from any app at any time.

Determine whether your app was already granted the permission

To check if the user has already granted your app a particular permission, pass that permission into the ContextCompat.checkSelfPermission() method. This method returns either PERMISSION_GRANTED or PERMISSION_DENIED, depending on whether your app has the permission.

Explain why your app needs the permission

If the ContextCompat.checkSelfPermission() method returns PERMISSION_DENIED, call shouldShowRequestPermissionRationale(). If this method returns true, show an educational UI to the user. In this UI, describe why the feature, which the user wants to enable, needs a particular permission.

Request permissions

After the user views an educational UI, or the return value of shouldShowRequestPermissionRationale() indicates that you don't need to show an educational UI this time, request the permission. Users see a system permission dialog, where they can choose whether to grant a particular permission to your app.

Traditionally, you manage a request code yourself as part of the permission request and include this request code in your permission callback logic. Another option is to use the RequestPermission contract, included in an AndroidX library, where you allow the system to manage the permission request code for you. Because using the RequestPermission contract simplifies your logic, it's recommended that you use it when possible.

Allow the system to manage the permission request code

To allow the system to manage the request code that's associated with a permissions request, add a dependency on the androidx.activity library in your module's build.gradle file. Use version 1.2.0 or later of the library.

You can then use one of the following classes:

The following steps show how to use the RequestPermission contract. The process is nearly the same for the RequestMultiplePermissions contract.

  1. In your activity or fragment's initialization logic, pass in an implementation of ActivityResultCallback into a call to registerForActivityResult(). The ActivityResultCallback defines how your app handles the user's response to the permission request.

    Keep a reference to the return value of registerForActivityResult(), which is of type ActivityResultLauncher.

  2. To display the system permissions dialog when necessary, call the launch() method on the instance of ActivityResultLauncher that you saved in the previous step.

    After launch() is called, the system permissions dialog appears. When the user makes a choice, the system asynchronously invokes your implementation of ActivityResultCallback, which you defined in the previous step.

    Note: Your app cannot customize the dialog that appears when you call launch(). To provide more information or context to the user, change your app's UI so that it's easier for users to understand why a feature in your app needs a particular permission. For example, you might change the text in the button that enables the feature.

    Also, the text in the system permission dialog references the permission group associated with the permission that you requested. This permission grouping is designed for system ease-of-use, and your app shouldn't rely on permissions being within or outside of a specific permission group.

The following code snippet shows how to handle the permissions response:

Kotlin

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
    registerForActivityResult(RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // features requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    }

Java

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher, as an instance variable.
private ActivityResultLauncher<String> requestPermissionLauncher =
    registerForActivityResult(new RequestPermission(), isGranted -> {
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // features requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    });

And this code snippet demonstrates the recommended process of checking for a permission, and requesting a permission from the user when necessary:

Kotlin

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
    }
    shouldShowRequestPermissionRationale(...) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected. In this UI,
        // include a "cancel" or "no thanks" button that allows the user to
        // continue using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        // The registered ActivityResultCallback gets the result of this request.
        requestPermissionLauncher.launch(
                Manifest.permission.REQUESTED_PERMISSION)
    }
}

Java

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected. In this UI,
    // include a "cancel" or "no thanks" button that allows the user to
    // continue using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    // The registered ActivityResultCallback gets the result of this request.
    requestPermissionLauncher.launch(
            Manifest.permission.REQUESTED_PERMISSION);
}

Manage the permission request code yourself

As an alternative to allowing the system to manage the permission request code, you can manage the permission request code yourself. To do so, include the request code in a call to requestPermissions().

The following code snippet demonstrates how to request a permission using a request code:

Kotlin

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
        performAction(...)
    }
    shouldShowRequestPermissionRationale(...) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected. In this UI,
        // include a "cancel" or "no thanks" button that allows the user to
        // continue using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        requestPermissions(CONTEXT,
                arrayOf(Manifest.permission.REQUESTED_PERMISSION),
                REQUEST_CODE)
    }
}

Java

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected. In this UI,
    // include a "cancel" or "no thanks" button that allows the user to
    // continue using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    requestPermissions(CONTEXT,
            new String[] { Manifest.permission.REQUESTED_PERMISSION },
            REQUEST_CODE);
}

After the user responds to the system permissions dialog, the system then invokes your app's implementation of onRequestPermissionsResult(). The system passes in the user response to the permission dialog, as well as the request code that you defined, as shown in the following code snippet:

Kotlin

override fun onRequestPermissionsResult(requestCode: Int,
        permissions: Array<String>, grantResults: IntArray) {
    when (requestCode) {
        PERMISSION_REQUEST_CODE -> {
            // If request is cancelled, the result arrays are empty.
            if ((grantResults.isNotEmpty() &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            } else {
                // Explain to the user that the feature is unavailable because
                // the features requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return
        }

        // Add other 'when' lines to check for other
        // permissions this app might request.
        else -> {
            // Ignore all other requests.
        }
    }
}

Java

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
        int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            }  else {
                // Explain to the user that the feature is unavailable because
                // the features requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return;
        }
        // Other 'case' lines to check for other
        // permissions this app might request.
    }
}

Handle permission denial

If the user denies a permission request, your app should help users understand the implications of denying the permission. In particular, your app should make users aware of the features that don't work because of the missing permission. When you do so, keep the following best practices in mind:

  • Guide the user's attention. Highlight a specific part of your app's UI where there's limited functionality because your app doesn't have the necessary permission. Several examples of what you could do include the following:

    • Show a message where the feature's results or data would have appeared.
    • Display a different button that contains an error icon and color.
  • Be specific. Don't display a generic message; instead, mention which features are unavailable because your app doesn't have the necessary permission.

  • Don't block the user interface. In other words, don't display a full-screen warning message that prevents users from continuing to use your app at all.

At the same time, your app should respect the user's decision to deny a permission. Starting in Android 11 (API level 30), if the user taps Deny for a specific permission more than once during your app's lifetime of installation on a device, the user doesn't see the system permissions dialog if your app requests that permission again. The user's action implies "don't ask again." On previous versions, users would see the system permissions dialog each time your app requested a permission, unless the user had previously selected a "don't ask again" checkbox or option.

In certain situations, the permission might be denied automatically, without the user taking any action. (Similarly, a permission might be granted automatically as well.) It's important to not assume anything about automatic behavior. Each time your app needs to access functionality that requires a permission, you should check that your app is still granted that permission.

To provide the best user experience when asking for app permissions, also see App permissions best practices.

One-time permissions

The option called 'Only this time' is the second of three buttons in
    the dialog.
Figure 1. System dialog that appears when an app requests a one-time permission.

Starting in Android 11 (API level 30), whenever your app requests a permission related to location, microphone, or camera, the user-facing permissions dialog contains an option called Only this time, as shown in Figure 1. If the user selects this option in the dialog, your app is granted a temporary one-time permission.

Your app can then access the related data for a period of time that depends on your app's behavior and the user's actions:

  • While your app's activity is visible, your app can access the data.
  • If the user sends your app to the background, your app can continue to access the data for a short period of time.
  • If you launch a foreground service while the activity is visible, and the user then moves your app to the background, your app can continue to access the data until that foreground service stops.
  • If the user revokes the one-time permission, such as in system settings, your app cannot access the data, regardless of whether you launched a foreground service. As with any permission, if the user revokes your app's one-time permission, your app's process terminates.

When the user next opens your app and a feature in your app requests access to location, microphone, or camera, the user is prompted for the permission again.

Auto-reset permissions of unused apps

If your app targets Android 11 (API level 30) or higher and isn't used for a few months, the system protects user data by automatically resetting the sensitive runtime permissions that the user had granted your app. This action has the same effect as if the user viewed a permission in system settings and changed your app's access level to Deny.

If your app follows best practices for requesting permissions at runtime, you don't need to make any changes to your app.

Request user to disable auto-reset

If needed, you can ask the user to prevent the system from resetting your app's permissions. This is useful in situations where users expect your app to work primarily in the background, even without the user interacting with your app, such as in the following use cases:

Figure 2. User has disabled the auto-resetting of permissions for a given app.
  • Provide family safety.
  • Sync data.
  • Communicate with smart devices.
  • Pair to companion devices.

To direct the user to your app's page in system settings, invoke an intent that includes the Intent.ACTION_AUTO_REVOKE_PERMISSIONS intent action. From this screen, users can prevent the system from resetting your app's permissions by doing the following:

  1. Tap Permissions, which loads the App permissions settings screen.
  2. Turn off the option called Remove permissions if app isn't used, as shown in Figure 2.

Determine whether auto-reset is disabled

To check whether auto-reset functionality is disabled for your app, call isAutoRevokeWhitelisted(). If this method returns true, then the system doesn't auto-reset your app's permissions.

Request to become the default handler if necessary

Some apps depend on access to sensitive user information related to call logs and SMS messages. If you want to request the permissions specific to call logs and SMS messages and publish your app to the Play Store, you must prompt the user to set your app as the default handler for a core system function before requesting these runtime permissions.

For more information on default handlers, including guidance on showing a default handler prompt to users, see the guide on permissions used only in default handlers.

Test runtime permissions

This section describes how to test several aspects of runtime permissions.

Grant all runtime permissions

To grant all runtime permissions automatically when you install an app on an emulator or test device, use the -g option for the adb shell install command, as demonstrated in the following code snippet:

adb shell install -g PATH_TO_APK_FILE

Perform an auto-reset of your app's permissions

To verify that the system resets your app's permissions, do the following:

  1. Save the default amount of time that the system waits to reset an app's permissions. That way, you can restore it after testing:

    threshold=$(adb shell device_config get permissions \
      auto_revoke_unused_threshold_millis2)
    
  2. Reduce the amount of time that the system waits to reset the permissions. In the following example, the system is modified such that it resets an app's permissions only one second after you stop interacting with an app:

    adb shell device_config put permissions \
      auto_revoke_unused_threshold_millis2 1000
    
  3. Invoke the auto-reset process manually, as shown in the following snippet. Make sure that the test device has been turned on for a short while, about 45 seconds, before you run this command.

    adb shell cmd jobscheduler run -u 0 -f \
      com.google.android.permissioncontroller 2
    
  4. Verify that your app can handle the auto-reset event.

  5. Restore the default amount of time that the system waits before it auto-resets an app's permissions:

    adb shell device_config put permissions \
      auto_revoke_unused_threshold_millis2 $threshold
    

Additional resources

For additional information about permissions, read these articles:

To learn more about requesting permissions, download the following sample apps:

  • Android RuntimePermissionsBasic Sample Java | Kotlin