It's easy for an app to overwhelm a user with permission requests. If a user finds the app frustrating to use, or the user is worried about what the app might be doing with the user's information, they may avoid using the app or uninstall it entirely. The following best practices can help you avoid such bad user experiences.
Consider Using an Intent
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
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 complete control, you can use an
to request an image. When you send the intent, the system prompts the user to
choose a camera app (if there isn't already a default camera app).
The user takes a picture with the selected camera app, and that app returns
the picture to your app's
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:
- Your app has full control over the user experience when you perform the operation. However, such broad control adds to the complexity of your task, since you need to design an appropriate UI.
- The user is prompted to give permission once, either at run time or at install time (depending on the user's Android version). After that, your app can perform the operation without requiring additional interaction from the user. However, if the user doesn't grant the permission (or revokes it later on), your app becomes unable to perform the operation at all.
If you use an intent:
- You do not have to design the UI for the operation. The app that handles the intent provides the UI. However, this means you have no control over the user experience. The user could be interacting with an app you've never seen.
- If the user does not have a default app for the operation, the system prompts the user to choose an app. If the user does not designate a default handler, they may have to go through an extra dialog every time they perform the operation.
Only Ask for Permissions You Need
Every time you ask for a permission, you force the user to make a decision. You should minimize the number of times you make these requests. If the user is running Android 6.0 (API level 23) or later, every time the user tries some new app feature that requires a permission, the app has to interrupt the user's work with a permission request. If the user is running an earlier version of Android, the user has to grant every one of the app's permissions when installing the app; if the list is too long or seems inappropriate, the user may decide not to install your app at all. For these reasons, you should minimize the number of permissions your app needs.
Quite often your app can avoid requesting a permission by using an intent instead. If a feature is not a core part of your app's functionality, you should consider handing the work over to another app, as described in Consider Using An Intent.
Don't Overwhelm the User
If the user is running Android 6.0 (API level 23) or later, the user has to grant your app its permissions while they are running the app. 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. It might make sense to ask for all of those 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 the
READ_CONTACTS 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
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
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
wants 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
One way to inform the user 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 could 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 could then call
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.
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. Under the new permissions model, you can no longer make that assumption.
The following tips will help you identify 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. Remember, 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.
- 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.