• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Permissions Best Practices
2page.tags=permissions
3helpoutsWidget=true
4
5@jd:body
6
7<div id="tb-wrapper">
8  <div id="tb">
9
10<h2>In this document</h2>
11<ul>
12  <li><a href="#perms-vs-intents">Consider Using an Intent</a></li>
13
14  <li><a href="#dont-overwhelm">Don't Overwhelm the User</a></li>
15
16  <li><a href="#explain">Explain Why You Need Permissions</a></li>
17
18  <li><a href="#testing">Test for Both Permissions Models</a></li>
19
20</ul>
21
22<h2>You should also read</h2>
23  <ul>
24    <li><a href="{@docRoot}training/basics/intents/index.html">Interacting
25      with Other Apps</a></li>
26  </ul>
27
28</div>
29</div>
30
31
32<p>
33It's easy for an app to overwhelm a user with permission requests. If a user
34finds the app frustrating to use, or the user is worried about what the app
35might be doing with the user's information, they may avoid using the app or
36uninstall it entirely. The following best practices can help you avoid such
37bad user experiences.
38</p>
39
40<h2 id="perms-vs-intents">Consider Using an Intent</h2>
41
42<p>
43  In many cases, you can choose between two ways for your app to perform a
44  task. You can have your app ask for permission to perform the operation
45  itself. Alternatively, you can have the app use an <em>intent</em> to have
46  another app perform the task.
47</p>
48
49<p>
50  For example, suppose your app needs to be able to take pictures with the
51  device camera. Your app can request the {@link
52  android.Manifest.permission#CAMERA CAMERA} permission, which allows your app
53  to access the camera directly. Your app would then use the camera APIs to
54  control the camera and take a picture. This approach gives your app full
55  control over the photography process, and lets you incorporate the camera UI
56  into your app.
57</p>
58
59<p>
60  However, if you don't need such complete control, you can use an {@link
61  android.provider.MediaStore#ACTION_IMAGE_CAPTURE ACTION_IMAGE_CAPTURE} intent
62  to request an image. When you send the intent, the system prompts the user to
63  choose a camera app (if there isn't already a default camera app).
64  The user takes a picture with the selected camera app, and that app returns
65  the picture to your app's {@link
66  android.app.Activity#onActivityResult onActivityResult()} method.
67</p>
68
69<p>
70  Similarly, if you need to make a phone call, access the user's contacts, and
71  so on, you can do that by creating an appropriate intent, or you can request
72  the permission and access the appropriate objects directly. There are
73  advantages and disadvantages to each approach.
74</p>
75
76<p>
77  If you use permissions:
78</p>
79
80<ul>
81  <li>Your app has full control over the user experience when you perform the
82  operation. However, such broad control adds to the complexity of your task,
83  since you need to design an appropriate UI.
84  </li>
85
86  <li>The user is prompted to give permission once, either at run time or at
87  install time (depending on the user's Android version). After that, your app
88  can perform the operation without requiring additional interaction from the
89  user. However, if the user doesn't grant the permission (or revokes it later
90  on), your app becomes unable to perform the operation at all.
91  </li>
92</ul>
93
94<p>
95  If you use an intent:
96</p>
97
98<ul>
99  <li>You do not have to design the UI for the operation. The app that handles
100  the intent provides the UI. However, this means you have
101  no control over the user experience. The user could be interacting with an
102  app you've never seen.
103  </li>
104
105  <li>If the user does not have a default app for the operation, the system
106  prompts the user to choose an app. If the user does not designate a default
107  handler, they may have to go
108  through an extra dialog every time they perform the operation.
109  </li>
110</ul>
111
112<h2 id="ask-neccessary">Only Ask for Permissions You Need</h2>
113
114<p>
115  Every time you ask for a permission, you force the user to make a decision.
116  You should minimize the number of times you make these requests. If the user
117  is running Android 6.0 (API level 23) or later, every time the user tries
118  some new app feature that requires a permission, the app has to interrupt the
119  user's work with a permission request. If the user is running an earlier
120  version of Android, the user has to grant every one of the app's permissions
121  when installing the app; if the list is too long or seems inappropriate, the
122  user may decide not to install your app at all. For these reasons, you should
123  minimize the number of permissions your app needs.
124</p>
125
126<p>
127  Quite often your app can avoid requesting a permission by using an
128  <em>intent</em> instead. If a feature is not a core part of your app's
129  functionality, you should consider handing the work over to another app, as
130  described in <a href="#perms-vs-intents">Consider Using An Intent</a>.
131</p>
132
133<h2 id="dont-overwhelm">Don't Overwhelm the User</h2>
134
135<p>
136  If the user is running Android 6.0 (API level 23) or later, the user has to
137  grant your app its permissions while they are running the app. If you
138  confront the user with a lot of requests for permissions at once, you may
139  overwhelm the user and cause them to quit your app. Instead, you should ask
140  for permissions as you need them.
141</p>
142
143<p>
144  In some cases, one or more permissions might be absolutely essential to your
145  app. It might make sense to ask for all of those permissions as soon as the
146  app launches. For example, if you make a photography app, the app would need
147  access to the device camera. When the user launches the app for the first
148  time, they won't be surprised to be asked for permission to use the camera.
149  But if the same app also had a feature to share photos with the user's
150  contacts, you probably should <em>not</em> ask for the {@link
151  android.Manifest.permission#READ_CONTACTS READ_CONTACTS} permission at first
152  launch. Instead, wait until the user tries to use the "sharing" feature and
153  ask for the permission then.
154</p>
155
156<p>
157  If your app provides a tutorial, it may make sense to request the app's
158  essential permissions at the end of the tutorial sequence.
159</p>
160
161<h2 id="explain">Explain Why You Need Permissions</h2>
162
163<p>
164  The permissions dialog shown by the system when you call
165  {@link android.support.v4.app.ActivityCompat#requestPermissions
166  requestPermissions()} says what permission your app wants, but doesn't say
167  why. In some cases, the user may find that puzzling. It's a good idea to
168  explain to the user why your app wants the permissions before calling
169  {@link android.support.v4.app.ActivityCompat#requestPermissions
170  requestPermissions()}.
171</p>
172
173<p>
174  For example, a photography app might want to use location services so it can
175  geotag the photos. A typical user might not understand that a photo can
176  contain location information, and would be puzzled why their photography app
177  wants to know the location. So in this case, it's a good idea for the app to
178  tell the user about this feature <em>before</em> calling
179  {@link android.support.v4.app.ActivityCompat#requestPermissions
180  requestPermissions()}.
181</p>
182
183<p>
184  One way to inform the user is to incorporate these requests into an app
185  tutorial. The tutorial can show each of the app's features in turn, and as it
186  does this, it can explain what permissions are needed. For example, the
187  photography app's tutorial could demonstrate its "share photos with your
188  contacts" feature, then tell the user that they need to give permission for
189  the app to see the user's contacts. The app could then call {@link
190  android.support.v4.app.ActivityCompat#requestPermissions
191  requestPermissions()} to ask the user for that access. Of course, not every
192  user is going to follow the tutorial, so you still need to check for and
193  request permissions during the app's normal operation.
194</p>
195
196<h2 id="testing">Test for Both Permissions Models</h2>
197
198<p>
199  Beginning with Android 6.0 (API level 23), users grant and revoke app
200  permissions at run time, instead of doing so when they install the app. As a
201  result, you'll have to test your app under a wider range of conditions. Prior
202  to Android 6.0, you could reasonably assume that if your app is running at
203  all, it has all the permissions it declares in the app manifest. Under the
204  new permissions model, you can no longer make that assumption.
205</p>
206
207<p>
208  The following tips will help you identify permissions-related code problems
209  on devices running API level 23 or higher:
210</p>
211
212<ul>
213  <li>Identify your app’s current permissions and the related code paths.
214  </li>
215
216  <li>Test user flows across permission-protected services and data.
217  </li>
218
219  <li>Test with various combinations of granted or revoked permissions. For
220  example, a camera app might list {@link android.Manifest.permission#CAMERA
221  CAMERA}, {@link android.Manifest.permission#READ_CONTACTS READ_CONTACTS}, and
222  {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION}
223  in its manifest. You should test the app with each of these permissions
224  turned on and off, to make sure the app can handle all permission
225  configurations gracefully. Remember, beginning with Android 6.0 the user can
226  turn permissions on or off for <em>any</em> app, even an app that targets API
227  level 22 or lower.
228  </li>
229
230  <li>Use the <a href="{@docRoot}tools/help/adb.html">adb</a> tool to manage
231  permissions from the command line:
232    <ul>
233      <li>List permissions and status by group:
234
235        <pre class="no-pretty-print">$ adb shell pm list permissions -d -g</pre>
236      </li>
237
238      <li>Grant or revoke one or more permissions:
239
240        <pre class="no-pretty-print">$ adb shell pm [grant|revoke] &lt;permission-name&gt; ...</pre>
241      </li>
242    </ul>
243  </li>
244
245  <li>Analyze your app for services that use permissions.
246  </li>
247</ul>
248