| page.title=Best Practices for App Permissions |
| page.metaDescription=How to manage permissions to give users context and control. |
| page.tags=permissions, user data |
| meta.tags="permissions", "user data" |
| page.image=images/cards/card-user-permissions_2x.png |
| |
| page.article=true |
| @jd:body |
| |
| <div id="tb-wrapper"> |
| <div id="tb"> |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#tenets_of_working_with_android_permissions">Tenets</a></li> |
| <li><a href="#version_specific_details_permissions_in_m">Permissions in Android |
| 6.0+</h2></a></li> |
| <li><a href="#avoid_requesting_unnecessary_permissions">Avoid Requesting |
| Unnecessary Permissions</h2></a> |
| <ol> |
| <li><a href="#a_camera_contact_access_with_real-time_user_requests">Camera/Contact |
| access with realtime user requests</a></li> |
| <li><a href="#b_running_in_the_background_after_losing_audio_focus">Running in |
| the background after losing audio focus</a></li> |
| <li><a href="#c_determine_the_device_your_instance_is_running_on">Determine the |
| device your instance is running on</a></li> |
| <li><a href="#d_create_a_unique_identifier_for_advertising_or_user_analytics"> |
| Create a unique identifier for advertising or user analytics</a></li> |
| </ol> |
| </li> |
| <li><a href="#know_the_libraries_you're_working_with">Know the Libraries You're |
| Working With</a></li> |
| <li><a href="#be_transparent">Be Transparent</a></li> |
| </ol> |
| <h2>You should also read</h2> |
| <ol> |
| <li><a href="{@docRoot}guide/topics/security/permissions.html">System Permissions</a></li> |
| <li><a href="{@docRoot}training/permissions/index.html">Working with System |
| Permissions</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p> |
| 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. |
| </p> |
| |
| <p> |
| For a more general look at Android permissions, please see <a href= |
| "{@docRoot}training/articles/user-data-overview.html">Permissions |
| and User Data</a>. For details on how to work with permissions in your code, |
| see <a href="{@docRoot}training/permissions/index.html">Working with System Permissions</a>. |
| For best practices for working with unique identifiers, please see <a href= |
| "{@docRoot}training/articles/user-data-ids.html">Best Practices for |
| Unique Identifiers</a>. |
| </p> |
| |
| <h2 id="tenets_of_working_with_android_permissions">Tenets of Working |
| with Android Permissions</h2> |
| |
| <p> |
| We recommend following these tenets when working with Android permissions: |
| </p> |
| |
| <p> |
| <em><strong>#1: Only use the permissions necessary for your app to |
| work</strong></em>. 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. |
| </p> |
| |
| <p> |
| <em><strong>#2: Pay attention to permissions required by |
| libraries.</strong></em> 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. |
| </p> |
| |
| <p> |
| <em><strong>#3: Be transparent.</strong></em> 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. |
| </p> |
| |
| <p> |
| <em><strong>#4: Make system accesses explicit.</strong></em> 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. |
| </p> |
| |
| <p> |
| The remaining sections of this guide elaborate on these rules in the context |
| of developing Android applications. |
| </p> |
| |
| <h2 id="version_specific_details_permissions_in_m">Permissions in Android 6.0+</h2> |
| |
| <p> |
| Android 6.0 Marshmallow introduced a <a href= |
| "{@docRoot}training/permissions/requesting.html">new permissions model</a> 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: |
| </p> |
| |
| <p> |
| <em><strong>Increased situational context</strong></em>: 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. |
| </p> |
| |
| <p> |
| <em><strong>Greater flexibility in granting permissions</strong></em>: Users |
| can deny access to individual permissions at the time they’re requested |
| <em>and</em> 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. |
| </p> |
| |
| <p> |
| <em><strong>Increased transactional burden</strong></em>: 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. |
| </p> |
| |
| <h2 id="avoid_requesting_unnecessary_permissions">Avoid Requesting |
| Unnecessary Permissions</h2> |
| |
| <p> |
| This section provides alternatives to common use-cases that will help you |
| limit the number of permission requests you make. Since the number and type |
| of user-surfaced permissions requested affects downloads compared to other |
| similar apps requesting fewer permissions, it’s best to avoid requesting |
| permissions for unnecessary functionality. |
| </p> |
| |
| <h3 id="a_camera_contact_access_with_real-time_user_requests">Camera/contact |
| access with realtime user requests</h3> |
| |
| <p> |
| <em>In this case, you need occasional access to the device's camera or |
| contact information and don’t mind the user being asked every time you need |
| access.</em> |
| </p> |
| |
| <p> |
| If your requirement for access to user data is infrequent — in other |
| words, it's not unacceptably disruptive for the user to be presented with a |
| runtime dialogue each time you need to access data — you can use an |
| <em>intent based request</em>. Android provides some system intents that |
| applications can use without requiring permissions because the user chooses |
| what, if anything, to share with the app at the time the intent based request |
| is issued. |
| </p> |
| |
| <p> |
| For example, an intent action type of <code><a href= |
| "{@docRoot}reference/android/provider/MediaStore.html#ACTION_IMAGE_CAPTURE">MediaStore.ACTION_IMAGE_CAPTURE</a></code> |
| or <code><a href= |
| "{@docRoot}reference/android/provider/MediaStore.html#ACTION_VIDEO_CAPTURE">MediaStore.ACTION_VIDEO_CAPTURE</a></code> |
| can be used to capture images or videos without directly using the <a href= |
| "{@docRoot}reference/android/hardware/Camera.html">Camera</a> object (or |
| requiring the permission). In this case, the system intent will ask for the |
| user’s permission on your behalf every time an image is captured. |
| </p> |
| |
| <h3 id="b_running_in_the_background_after_losing_audio_focus">Running in |
| the background after losing audio focus</h3> |
| |
| <p> |
| <em>In this case, your application needs to go into the background when the |
| user gets a phone call and refocus only once the call stops.</em> |
| </p> |
| |
| <p> |
| The common approach in these cases - for example, a media player muting or |
| pausing during a phone call - is to listen for changes in the call state |
| using <code>PhoneStateListener</code> or listening for the broadcast of |
| <code>android.intent.action.PHONE_STATE</code>. The problem with this |
| solution is that it requires the <code>READ_PHONE_STATE</code> permission, |
| which forces the user to grant access to a wide cross section of sensitive |
| data such as their device and SIM hardware IDs and the phone number of the |
| incoming call. |
| </p> |
| |
| <p> |
| You can avoid this by requesting <code>AudioFocus</code> for your app, which |
| doesn't require explicit permissions (because it does not access sensitive |
| information). Simply put the code required to background your audio in the |
| <code><a href= |
| "{@docRoot}reference/android/media/AudioManager.OnAudioFocusChangeListener.html#onAudioFocusChange(int)"> |
| onAudioFocusChange()</a></code> event handler and it will run automatically |
| when the OS shifts its audio focus. More detailed documentation on how to do |
| this can be found <a href= |
| "{@docRoot}training/managing-audio/audio-focus.html">here</a>. |
| </p> |
| |
| <h3 id="c_determine_the_device_your_instance_is_running_on">Determine the |
| device your instance is running on</h3> |
| |
| <p> |
| <em>In this case, you need a unique identifier to determine which device the |
| instance of your app is running on.</em> |
| </p> |
| |
| <p> |
| Applications may have device-specific preferences or messaging (e.g., saving |
| a device-specific playlist for a user in the cloud so that they can have a |
| different playlist for their car and at home). A common solution is to |
| leverage device identifiers such as <code>Device IMEI</code>, but this |
| requires the <code>Device ID and call information</code> |
| permission group (<code>PHONE</code> in M+). It also uses an identifier which |
| cannot be reset and is shared across all apps. |
| </p> |
| |
| <p> |
| There are two alternatives to using these types of identifiers: |
| </p> |
| |
| <ol> |
| <li> Use the <code>com.google.android.gms.iid</code> InstanceID API. |
| <code>getInstance(Context context).getID()<strong></code> </strong>will return a |
| unique device identifier for your application instance. The |
| result is an app instance scoped identifier that can be used as a key when |
| storing information about the app and is reset if the user re-installs the app. |
| <li> Create your own identifier that’s scoped to your app’s storage using basic |
| system functions like <a |
| href="{@docRoot}reference/java/util/UUID.html#randomUUID()"><code>randomUUID()</code></a>.</li> |
| </ol> |
| |
| <h3 id="d_create_a_unique_identifier_for_advertising_or_user_analytics">Create a unique |
| identifier for advertising or user analytics</h3> |
| |
| <p> |
| <em>In this case, you need a unique identifier for building a profile for |
| users who are not signed in to your app (e.g., for ads targeting or measuring |
| conversions).</em> |
| </p> |
| |
| <p> |
| Building a profile for advertising and user analytics sometimes requires an |
| identifier that is shared across other applications. Common solutions for |
| this involve leveraging device identifiers such as <code>Device IMEI</code>, |
| which requires the <code>Device ID</code> <code>and call information</code> |
| permission group (<code>PHONE</code> in API level 23+) and cannot be reset by |
| the user. In any of these cases, in addition to using a non-resettable |
| identifier and requesting a permission that might seem unusual to users, you |
| will also be in violation of the <a href= |
| "https://play.google.com/about/developer-content-policy.html">Play Developer |
| Program Policies</a>. |
| </p> |
| |
| <p> |
| Unfortunately, in these cases using the |
| <code>com.google.android.gms.iid</code> InstanceID API or system functions to |
| create an app-scoped ID are not appropriate solutions because the ID may need |
| to be shared across apps. An alternative solution is to use the |
| <code>Advertising Identifier</code> available from the <code><a href= |
| "{@docRoot}reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html"> |
| AdvertisingIdClient.Info</a></code> class via the <code>getId()</code> |
| method. You can create an <code>AdvertisingIdClient.Info</code> object using |
| the <code>getAdvertisingIdInfo(Context)</code> method and call the |
| <code>getId()</code> method to use the identifier. <em><strong>Note that this |
| method is blocking</strong></em>, so you should not call it from the main |
| thread; a detailed explanation of this method is available <a href= |
| "{@docRoot}google/play-services/id.html">here</a>. |
| </p> |
| |
| <h2 id="know_the_libraries_you're_working_with">Know the Libraries You're |
| Working With</h2> |
| |
| <p> |
| Sometimes permissions are required by the libraries you use in your app. For |
| example, ads and analytics libraries may require access to the |
| <code>Location</code> or <code>Identity</code> permissions groups to |
| implement the required functionality. But from the user’s point of view, the |
| permission request comes from your app, not the library. |
| </p> |
| |
| <p> |
| Just as users select apps that use fewer permissions for the same |
| functionality, developers should review their libraries and select |
| third-party SDKs that are not using unnecessary permissions. For example, try |
| to avoid libraries that require the <code>Identity</code> permission group |
| unless there is a clear user-facing reason why the app needs those permissions. |
| In particular, for libraries that provide location functionality, make sure you |
| are not required to request the <code>FINE_LOCATION</code> permission unless |
| you are using location-based targeting functionality. |
| </p> |
| |
| <h2 id="be_transparent">Be Transparent</h2> |
| |
| <p>You should inform your users about what you’re accessing and why. Research shows |
| that users are much less uncomfortable with permissions requests if they know |
| why the app needs them. A user study showed that:</p> |
| |
| <div style="padding:.5em 2em;"> |
| <div style="border-left:4px solid #999;padding:0 1em;font-style:italic;"> |
| <p>...a user’s willingness to grant a given permission to a given mobile app is |
| strongly influenced by the purpose associated with such a permission. For |
| instance a user’s willingness to grant access to his or her location will vary |
| based on whether the request is required to support the app’s core |
| functionality or whether it is to share this information with an advertising |
| network or an analytics company.<span |
| style="font-size:.8em;color:#777"><sup><em><a |
| href="#references" style="color:#777;padding-left:.1em;">1</a></em></sup></span></p> |
| </div> |
| </div> |
| |
| <p> |
| Based on his group’s research, Professor Jason Hong from CMU concluded that, |
| in general: |
| </p> |
| |
| <div style="padding:.5em 2em;"> |
| <div style="border-left:4px solid #999;padding:0 1em;font-style:italic;"> |
| <p>...when people know why an app is using something as sensitive as their location — |
| for example, for targeted advertising — it makes them more comfortable than |
| when simply told an app is using their location.<span |
| style="font-size:.8em;color:#777"><sup><em><a |
| href="#references" style="color:#777;padding-left:.1em;">1</a></em></sup></span></p> |
| </div> |
| </div> |
| |
| <p> |
| 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: |
| </p> |
| |
| <ul> |
| <li> If you’re only using coarse location, let the user know this in your app |
| description or in help articles about your app. </li> |
| <li> 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.</li> |
| </ul> |
| |
| <p> |
| 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. |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| |
| <h2 id="references">References</h2> |
| |
| <p> |
| [1] <em>Modeling Users’ Mobile App Privacy Preferences: Restoring Usability |
| in a Sea of Permission Settings</em>, by J. Lin B. Liu, N. Sadeh and J. Hong. |
| In Proceedings of SOUPS 2014. |
| </p> |