Per bug, emphasized that if an app targets SDK 22 or lower, it uses the install-time permissions model even if it's running on M. However, also added the note that an M user can *revoke* an app's permissions after install, which can cause unpredictable behavior. See first comment for doc stage location. bug: 25470298 Change-Id: Ia05a1f784595e75bf7b6835dbfdeffcd458f0022
248 lines
9.5 KiB
Plaintext
248 lines
9.5 KiB
Plaintext
page.title=Permissions Best Practices
|
||
page.tags=permissions
|
||
helpoutsWidget=true
|
||
|
||
@jd:body
|
||
|
||
<div id="tb-wrapper">
|
||
<div id="tb">
|
||
|
||
<h2>In this document</h2>
|
||
<ul>
|
||
<li><a href="#perms-vs-intents">Consider Using an Intent</a></li>
|
||
|
||
<li><a href="#dont-overwhelm">Don't Overwhelm the User</a></li>
|
||
|
||
<li><a href="#explain">Explain Why You Need Permissions</a></li>
|
||
|
||
<li><a href="#testing">Test for Both Permissions Models</a></li>
|
||
|
||
</ul>
|
||
|
||
<h2>You should also read</h2>
|
||
<ul>
|
||
<li><a href="{@docRoot}training/basics/intents/index.html">Interacting
|
||
with Other Apps</a></li>
|
||
</ul>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<p>
|
||
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.
|
||
</p>
|
||
|
||
<h2 id="perms-vs-intents">Consider Using an Intent</h2>
|
||
|
||
<p>
|
||
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 <em>intent</em> to have
|
||
another app perform the task.
|
||
</p>
|
||
|
||
<p>
|
||
For example, suppose your app needs to be able to take pictures with the
|
||
device camera. Your app can request the {@link
|
||
android.Manifest.permission#CAMERA 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.
|
||
</p>
|
||
|
||
<p>
|
||
However, if you don't need such complete control, you can use an {@link
|
||
android.provider.MediaStore#ACTION_IMAGE_CAPTURE ACTION_IMAGE_CAPTURE} intent
|
||
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 {@link
|
||
android.app.Activity#onActivityResult onActivityResult()} method.
|
||
</p>
|
||
|
||
<p>
|
||
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.
|
||
</p>
|
||
|
||
<p>
|
||
If you use permissions:
|
||
</p>
|
||
|
||
<ul>
|
||
<li>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.
|
||
</li>
|
||
|
||
<li>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.
|
||
</li>
|
||
</ul>
|
||
|
||
<p>
|
||
If you use an intent:
|
||
</p>
|
||
|
||
<ul>
|
||
<li>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.
|
||
</li>
|
||
|
||
<li>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.
|
||
</li>
|
||
</ul>
|
||
|
||
<h2 id="ask-neccessary">Only Ask for Permissions You Need</h2>
|
||
|
||
<p>
|
||
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.
|
||
</p>
|
||
|
||
<p>
|
||
Quite often your app can avoid requesting a permission by using an
|
||
<em>intent</em> 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 <a href="#perms-vs-intents">Consider Using An Intent</a>.
|
||
</p>
|
||
|
||
<h2 id="dont-overwhelm">Don't Overwhelm the User</h2>
|
||
|
||
<p>
|
||
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.
|
||
</p>
|
||
|
||
<p>
|
||
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 <em>not</em> ask for the {@link
|
||
android.Manifest.permission#READ_CONTACTS READ_CONTACTS} permission at first
|
||
launch. Instead, wait until the user tries to use the "sharing" feature and
|
||
ask for the permission then.
|
||
</p>
|
||
|
||
<p>
|
||
If your app provides a tutorial, it may make sense to request the app's
|
||
essential permissions at the end of the tutorial sequence.
|
||
</p>
|
||
|
||
<h2 id="explain">Explain Why You Need Permissions</h2>
|
||
|
||
<p>
|
||
The permissions dialog shown by the system when you call
|
||
{@link android.support.v4.app.ActivityCompat#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.support.v4.app.ActivityCompat#requestPermissions
|
||
requestPermissions()}.
|
||
</p>
|
||
|
||
<p>
|
||
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 <em>before</em> calling
|
||
{@link android.support.v4.app.ActivityCompat#requestPermissions
|
||
requestPermissions()}.
|
||
</p>
|
||
|
||
<p>
|
||
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 {@link
|
||
android.support.v4.app.ActivityCompat#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.
|
||
</p>
|
||
|
||
<h2 id="testing">Test for Both Permissions Models</h2>
|
||
|
||
<p>
|
||
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.
|
||
</p>
|
||
|
||
<p>
|
||
The following tips will help you identify permissions-related code problems
|
||
on devices running API level 23 or higher:
|
||
</p>
|
||
|
||
<ul>
|
||
<li>Identify your app’s current permissions and the related code paths.
|
||
</li>
|
||
|
||
<li>Test user flows across permission-protected services and data.
|
||
</li>
|
||
|
||
<li>Test with various combinations of granted or revoked permissions. For
|
||
example, a camera app might list {@link android.Manifest.permission#CAMERA
|
||
CAMERA}, {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}, and
|
||
{@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}
|
||
in 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 <em>any</em> app, even an app that targets API
|
||
level 22 or lower.
|
||
</li>
|
||
|
||
<li>Use the <a href="{@docRoot}tools/help/adb.html">adb</a> tool to manage
|
||
permissions from the command line:
|
||
<ul>
|
||
<li>List permissions and status by group:
|
||
|
||
<pre class="no-pretty-print">$ adb shell pm list permissions -d -g</pre>
|
||
</li>
|
||
|
||
<li>Grant or revoke one or more permissions:
|
||
|
||
<pre class="no-pretty-print">$ adb shell pm [grant|revoke] <permission-name> ...</pre>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
|
||
<li>Analyze your app for services that use permissions.
|
||
</li>
|
||
</ul>
|