Permission requests protect sensitive information available from a device and should only be used when access to information is necessary for the functioning of your app. This document provides tips on ways you might be able to achieve the same (or better) functionality without requiring access to such information; it is not an exhaustive discussion of how permissions work in the Android operating system.
Tenets of working with Android permissions
We recommend following these tenets when working with Android permissions:
#1: Only use the permissions necessary for your app to work. Depending on how you are using the permissions, there may be another way to do what you need (system intents, identifiers, backgrounding for phone calls) without relying on access to sensitive information.
#2: Pay attention to permissions required by libraries. When you include a library, you also inherit its permission requirements. You should be aware of what you're including, the permissions they require, and what those permissions are used for.
#3: Be transparent. When you make a permissions request, be clear about what you’re accessing, and why, so users can make informed decisions. Make this information available alongside the permission request including install, runtime, or update permission dialogues.
#4: Make system accesses explicit. Providing continuous indications when you access sensitive capabilities (for example, the camera or microphone) makes it clear to users when you’re collecting data and avoids the perception that you're collecting data surreptitiously.
The remaining sections of this guide elaborate on these rules in the context of developing Android applications.
Permissions in Android 6.0+
Android 6.0 Marshmallow introduced a new permissions model that lets apps request permissions from the user at runtime, rather than prior to installation. Apps that support the new model request permissions when the app actually requires the services or data protected by the services. While this doesn't (necessarily) change overall app behavior, it does create a few changes relevant to the way sensitive user data is handled:
Increased situational context: Users are prompted at runtime, in the context of your app, for permission to access the functionality covered by those permission groups. Users are more sensitive to the context in which the permission is requested, and if there’s a mismatch between what you are requesting and the purpose of your app, it's even more important to provide detailed explanation to the user as to why you’re requesting the permission; whenever possible, you should provide an explanation of your request both at the time of the request and in a follow-up dialog if the user denies the request.
Greater flexibility in granting permissions: Users can deny access to individual permissions at the time they’re requested and in settings, but they may still be surprised when functionality is broken as a result. It’s a good idea to monitor how many users are denying permissions (e.g. using Google Analytics) so that you can either refactor your app to avoid depending on that permission or provide a better explanation of why you need the permission for your app to work properly. You should also make sure that your app handles exceptions created when users deny permission requests or toggle off permissions in settings.
Increased transactional burden: Users will be asked to grant access for permission groups individually and not as a set. This makes it extremely important to minimize the number of permissions you’re requesting because it increases the user burden for granting permissions and increases the probability that at least one of the requests will be denied.
Permissions that require becoming a default handler
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.
Know the libraries you're working with
Sometimes permissions are required by the libraries you use in your app. For
example, ads and analytics libraries may require access to the
LOCATION permissions group to implement the required
functionality. But from the user's point of view, the permission request comes
from your app, not the library.
Just as users select apps that use fewer permissions for the same
functionality, developers should review their libraries and select
third-party SDKs that aren't using unnecessary permissions. For example, if
you're using a library that provides location functionality, make sure you
aren't requesting the
FINE_LOCATION permission unless you're
using location-based targeting functionality.
Limit background access to location
When your app is running in the background, access to location should be critical to the app's core functionality and show a clear benefit to users.
Explain why you need permissions
The permissions dialog shown by the system when you call
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
Research shows that users are much more comfortable with permissions requests if they know why the app needs them. A user study showed that:
Based on his group’s research, Professor Jason Hong from CMU concluded that, in general:
As a result, if you’re only using a fraction of the API calls that fall under a permission group, it helps to explicitly list which of those permissions you're using, and why. For example:
- If you’re only using coarse location, let the user know this in your app description or in help articles about your app.
If you need access to SMS messages to receive authentication codes that protect the user from fraud, let the user know this in your app description and/or the first time you access the data.
Note: If your app targets Android 8.0 (API level 26) or higher, don't request the
READ_SMSpermission as part of verifying a user's credentials. Instead, generate an app-specific token using
createAppSpecificSmsToken(), then pass this token to another app or service that can send a verification SMS message.
Under certain conditions, it's also advantageous to let users know about sensitive data accesses in real-time. For example, if you’re accessing the camera or microphone, it’s usually a good idea to let the user know with a notification icon somewhere in your app, or in the notification tray (if the application is running in the background), so it doesn't seem like you're collecting data surreptitiously.
Ultimately, if you need to request a permission to make something in your app work, but the reason is not clear to the user, find a way to let the user know why you need the most sensitive permissions.
Test for both permissions models
Beginning with Android 6.0 (API level 23), users grant and revoke app permissions at run time, instead of doing so when they install the app. As a result, you'll have to test your app under a wider range of conditions. Prior to Android 6.0, you could reasonably assume that if your app is running at all, it has all the permissions it declares in the app manifest. Beginning with Android 6.0 the user can turn permissions on or off for any app, even an app that targets API level 22 or lower. You should test to ensure your app functions correctly whether or not it has any permissions.
The following tips will help you find permissions-related code problems on devices running API level 23 or higher:
- Identify your app’s current permissions and the related code paths.
- Test user flows across permission-protected services and data.
- Test with various combinations of granted or revoked permissions. For
example, a camera app might list
ACCESS_FINE_LOCATIONin its manifest. You should test the app with each of these permissions turned on and off, to make sure the app can handle all permission configurations gracefully.
- Use the adb tool to manage
permissions from the command line:
- List permissions and status by group:
$ adb shell pm list permissions -d -g
- Grant or revoke one or more permissions:
$ adb shell pm [grant|revoke] <permission-name> ...
- List permissions and status by group:
- Analyze your app for services that use permissions.
- Material Design guidelines for Android permissions
- Android Marshmallow 6.0: Asking For Permission: This video explains the Android runtime permission model and the right way to ask users for permissions.
- Explain why the app needs permissions
- Best practices for unique identifiers
 Modeling Users’ Mobile App Privacy Preferences: Restoring Usability in a Sea of Permission Settings, by J. Lin B. Liu, N. Sadeh and J. Hong. In Proceedings of SOUPS 2014.