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>
|