diff options
Diffstat (limited to 'docs/html/preview/features/runtime-permissions.jd')
| -rw-r--r-- | docs/html/preview/features/runtime-permissions.jd | 837 |
1 files changed, 640 insertions, 197 deletions
diff --git a/docs/html/preview/features/runtime-permissions.jd b/docs/html/preview/features/runtime-permissions.jd index 4a01010..2ee44ef 100644 --- a/docs/html/preview/features/runtime-permissions.jd +++ b/docs/html/preview/features/runtime-permissions.jd @@ -1,15 +1,53 @@ -page.title=Android M Preview Runtime Permissions - +page.title=Runtime Permissions +page.tags=previewresources, androidm +page.keywords=permissions, runtime, preview @jd:body +<div id="qv-wrapper"> + <div id="qv"> + <h2>Quickview</h2> + <ul> + <li>If your app targets the M Preview SDK, it prompts users to grant + permissions at runtime, instead of install time.</li> + <li>Users can revoke permissions at any time from the app Settings + screen.</li> + <li>Your app needs to check that it has the permissions it needs every + time it runs.</li> + </ul> + + <h2>In this document</h2> + <ol> + <li><a href="#overview">Overview</a></li> + <li><a href="#coding">Coding for Runtime Permissions</a></li> + <li><a href="#testing">Testing Runtime Permissions</a></li> + <li><a href="#best-practices">Best Practices</a></li> + </ol> + +<!-- + <h2>Related Samples</h2> + <ol> + <li></li> + </ol> +--> + +<!-- + <h2>See also</h2> + <ol> + <li></li> + </ol> +--> + </div> <!-- qv --> +</div> <!-- qv-wrapper --> + + <p> - The M Developer Preview introduces a new app permissions model which makes it - less frustrating for users to install and upgrade apps. If an app running on - M supports the new permissions model, the user does not have to grant any - permissions when they install or upgrade the app. Instead, the app requests - permissions as they are needed, and the system shows a dialog to the user - asking for the permission. + The M Developer Preview introduces a new app permissions model which + streamlines the process for users to install and upgrade apps. If an app + running on the M Preview supports the new permissions model, the user does not have to + grant any permissions when they install or upgrade the app. Instead, the app + requests permissions as it needs them, and the system shows a dialog to the + user asking for the permission. </p> <p> @@ -18,70 +56,122 @@ page.title=Android M Preview Runtime Permissions model on those devices. </p> -<h2> +<h2 id="overview"> Overview </h2> <p> - If an app's target SDK version is the M developer preview, that indicates - that the app uses the new permissions model: + With the M Developer Preview, the platform introduces a new app permissions + model. Here's a summary of the key components of this new model: </p> <ul> - <li>Permissions are divided into <em>permission groups</em>, based on their - functionality. For example, all permissions relating to the camera and photo - roll are grouped in the Camera permission group, - [link]android.permission-group.CAMERA[/link]. + <li> + <strong>Declaring Permissions:</strong> The app declares all the + permissions it needs in the manifest, as in earlier Android platforms. </li> - <li>The app declares all the permissions it needs in the manifest, as in - earlier Android platforms. + <li> + <strong>Permission Groups:</strong> Permissions are divided into + <em>permission groups</em>, based on their functionality. For example, the + <code>CONTACTS</code> permission group contains permissions to read and + write the user's contacts and profile information. </li> - <li>When the user installs or updates the app, the app is granted just those - permissions it requests that fall under <a href= - "https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_NORMAL"> - <code>PROTECTION_NORMAL</code></a>, as well as signature and system permissions, as - described below. The user is <em>not</em> prompted to grant any permissions - at this time. + <li> + <p><strong>Limited Permissions Granted at Install Time:</strong> When the + user installs or updates the app, the system grants the app all + permissions that the app requests that fall under {@link + android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}. + For example, alarm clock and internet permissions fall under {@link + android.content.pm.PermissionInfo#PROTECTION_NORMAL PROTECTION_NORMAL}, so + they are automatically granted at install time. + </p> + + <p>The system may also grant the app signature and system permissions, as + described in <a href="#system-apps">System apps and signature + permissions</a>. The user is <em>not</em> prompted to grant any permissions + at install time.</p> </li> - <li>When the app needs to perform any action that requires a permission, it - first checks whether it has that permission already. If it does not, it - requests to be granted that permission. + <li> + <strong>User Grants Permissions at Run-Time:</strong> When the app requests + a permission, the system shows a dialog to the user, then calls the app's + callback function to notify it whether the permission was granted. If a + user grants a permission, the app is given all permissions in that + permission's functional area that were declared in the app manifest. </li> - <li>When the app requests a permission, the system shows a dialog box to the - user, then calls the app's callback function to notify it whether the - permission was granted. If a user grants a permission, the app is given all - permissions in that permission's functional area that were declared in the - app manifest. +</ul> + +<p> + This permission model changes the way your app behaves for features that + require permissions. Here's a summary of the development practices you should + follow to adjust to this model: +</p> + +<ul> + + <li> + <strong>Always Check for Permissions:</strong> When the app needs to + perform any action that requires a permission, it should first check + whether it has that permission already. If it does not, it requests to be + granted that permission. </li> - <li>If the app is not granted an appropriate permission, it should handle the - failure cleanly. For example, if the permission is just needed for an added - feature, the app can disable that feature. If the permission is essential for - the app to function, the app might disable all its functionality and inform - the user that they need to grant that permission. + <li> + <strong>Handle Lack of Permissions Gracefully:</strong> If the app is not + granted an appropriate permission, it should handle the failure cleanly. + For example, if the permission is just needed for an added feature, the app + can disable that feature. If the permission is essential for the app to + function, the app might disable all its functionality and inform the user + that they need to grant that permission. </li> - <li>Users can always go to the app's <b>Settings</b> screen and turn on or - off any of the app's permissions. - <!-- insert screenshot of settings screen--> - If a user turns off an app's permissions, the app is - <em>not</em> notified. + <div class="figure" style="width:220px"> + <img src="images/app-permissions-screen.png" srcset= + "images/app-permissions-screen@2x.png 2x" alt="" width="220" height= + "375"> + <p class="img-caption"> + <strong>Figure 2.</strong> Permission screen in the app's Settings. + </p> + </div> + + <li> + <strong>Permissions are Revocable:</strong> Users can revoke an app's + permissions at any time. If a user turns off an app's permissions, the app + is <em>not</em> notified. Once again, your app should verify that it has + needed permissions before performing any restricted actions. </li> </ul> -<h3> - System Apps and Signature Permissions +<p class="note"> + <strong>Note:</strong> If an app targets the M Developer Preview, it + <em>must</em> use the new permissions model. +</p> + +<p> + As of the launch of the M Developer Preview, not all Google apps fully + implement the new permissions model. Google is updating these apps over + the course of the M Developer Preview to properly respect Permissions toggle + settings. +</p> + +<p class="note"> + <strong>Note:</strong> If your app has its own API surface, do not proxy + permissions without first ensuring the caller has the requisite permissions + to access that data. +</p> + +<h3 id="system-apps"> + System apps and signature permissions </h3> <p> - Ordinarily, an app is just granted the <a href= - "https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_NORMAL"> - <code>PROTECTION_NORMAL</code></a> permissions when it is installed. However, - under some circumstances the app is granted more permissions: + Ordinarily, when the user installs an app, the system only grants the app the + {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL + PROTECTION_NORMAL}. However, under some circumstances the system grants the + app more permissions: </p> <ul> @@ -89,37 +179,130 @@ page.title=Android M Preview Runtime Permissions the permissions listed in its manifest. </li> - <li>Apps are granted all permissions listed in the manifest that fall under - <a href= - "https://android-preview.googleplex.com/reference/android/content/pm/PermissionInfo.html#PROTECTION_SIGNATURE"> - PROTECTION_SIGNATURE</a>, if the app's signature matches the signature of - the app that declares the permissions. + <li>If the app requests permissions in the manifest that fall under {@link + android.content.pm.PermissionInfo#PROTECTION_SIGNATURE PROTECTION_SIGNATURE}, + and the app is signed with the same certificate as the app that declared + those permissions, the system grants the requesting app those permissions on + installation. </li> </ul> <p> In both cases, the user can still revoke permissions at any time by going to - the app's <b>Settings</b> screen, so the app should continue to check for - permissions at run time and request them if necessary. + the system's <strong>Settings</strong> screen and choosing <strong>Apps + ></strong> <i>app_name</i> <strong>> Permissions</strong>. The app + should continue to check for permissions at run time and request them if + necessary. </p> -<h3> - Forwards and Backwards Compatibility +<h3 id="compatibility"> + Forwards and backwards compatibility </h3> <p> - If an app does not target the M developer preview, it continues to use the - old permissions model even on M devices. When the app is installed, the - system asks the user to grant all permissions listed in the app's manifest. + If an app does not target the M Developer Preview, the app continues to use + the old permissions model even on M Preview devices. When the user installs + the app, the system asks the user to grant all permissions listed in the + app's manifest. +</p> + +<p class="note"> + <strong>Note:</strong> On devices running the M Developer Preview, a user can + turn off permissions for any app (including legacy apps) from the app's + Settings screen. If a user turns off permissions for a legacy app, the system + silently disables the appropriate functionality. When the app attempts to + perform an operation that requires that permission, the operation will not + necessarily cause an exception. Instead, it might return an empty data set, + signal an error, or otherwise exhibit unexpected behavior. For example, if you + query a calendar without permission, the method returns an empty data set. +</p> + +<p> + If you install an app using the new permissions model on a device that is not + running the M Preview, + the system treats it the same as any other app: the system asks + the user to grant all declared permissions at install time. +</p> + +<p class="note"> + <strong>Note:</strong> For the preview release, you must set the minimum SDK + version to the M Preview SDK to compile with the preview SDK. This means you + will not be able to test such apps on older platforms during the developer + preview. +</p> + +<h3 id="perms-vs-intents">Permissions versus intents</h3> + +<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 intent to have another app + perform the task. </p> <p> - If an app using the new permissions model is run on a pre-M device, the - system treats it the same as any other app. Once again, the system asks the - user to grant all declared permissions at install time. + For example, suppose your app needs to be able to take pictures with the + device camera. Your app can request the + <code>android.permission.CAMERA</code> 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> -<h2 id="">Coding for Runtime Permissions</h2> +<p> + However, if you don't need such control, you can just use an {@link + android.provider.MediaStore#ACTION_IMAGE_CAPTURE ACTION_IMAGE_CAPTURE} intent + to request an image. When you start the intent, the user is prompted to + choose a camera app (if there isn't already a default camera app), and that + app takes the picture. The camera 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, the first time you perform + the operation. 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="coding">Coding for Runtime Permissions</h2> <p> If your app targets the new M Developer Preview, you must use the new @@ -129,44 +312,47 @@ page.title=Android M Preview Runtime Permissions have them. </p> -<h3> - Enabling the New Permissions Model +<h3 id="enabling"> + Enabling the new permissions model </h3> <p> To enable the new M Developer Preview permissions model, set the app's - <a href= - "http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target"> - targetSdkVersion</a> attribute to "M". Doing this enables all the new - permissions features. + <code>targetSdkVersion</code> attribute to <code>"MNC"</code>, and + <code>compileSdkVersion</code> to <code>"android-MNC"</code>. Doing so + enables all the new permissions features. </p> -<!-- TODO: Insert manifest snippet --> +<p> + For the preview release, you must set <code>minSdkVersion</code> to + <code>"MNC"</code> to compile with the preview SDK. +</p> -<h3> - Designating a Permission for M Only +<h3 id="m-only-perm"> + Designating a permission for the M Preview only </h3> <p> - You can use the new <code><uses-permission-sdk-m></code> element in the - app manifest to indicate that a permission is only needed on the M platform. - If you declare a permission this way, then whenever the app is installed on - an older device, the user is not prompted to grant the permission and the - permission is not granted to the app. This allows you to add new permissions + You can use the new <code><uses-permission-sdk-m></code> element in the app manifest + to indicate that a permission is only needed on the M Developer Preview. If + you declare a permission this way, then whenever the app is installed on an + older device, the system does not prompt the user or grant the + permission to the app. By using the <code><uses-permission-sdk-m></code> + element, you can add new permissions to updated versions of your app without forcing users to grant permissions when they install the update. </p> <p> - If the app is running on a device with the M developer preview, + If the app is running on a device with the M Developer Preview, <code><uses-permission-sdk-m></code> behaves the same as - <code><uses-permission></code>. The user is not prompted to grant any - permissions when the app is installed, and the app requests permissions as - they are needed. + <code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code>. + The system does not prompt the user to grant any permissions when they install + the app, and the app requests permissions as they are needed. </p> <h3 id="prompting"> - Prompting for Permissions on the M Preview + Prompting for permissions </h3> <p> @@ -178,73 +364,348 @@ page.title=Android M Preview Runtime Permissions </p> <p> - An app should follow this workflow to request permissions on an Android M - device. The device can check what platform it's running on by checking the - value of {@link android.os.Build.VERSION#SDK_INT Build.VERSION.SDK_INT}. If - the device is running the M Developer Preview, {@link - android.os.Build.VERSION#SDK_INT SDK_INT} is 23. - <!-- TODO: Confirm this number --> + If your app runs on a device that has SDK 22 or lower, the app uses the old + permissions model. When the user installs the app, they are prompted to grant + all the permissions your app requests in its manifest, except for those + permissions which are labeled with <code><uses-permission-sdk-m></code>. </p> -<ol> - <li>When the user tries to do something that requires a permission, the app - checks to see if it currently has permission to perform this operation. To do - this, the app calls - <a href="https://android-preview.googleplex.com/reference/android/content/Context.html#checkSelfPermission(java.lang.String)"><code>Context.CheckSelfPermission(<em>permission_name</em>)</code></a> . The - app should do this even if it knows the user has already granted that - permission, since the user can revoke an app's permissions at any time. For - example, if a user wants to use an app to take a picture, the app calls - <a href="https://android-preview.googleplex.com/reference/android/content/Context.html#checkSelfPermission(java.lang.String)"><code>Context.CheckSelfPermission(Manifest.permission.CAMERA)</code></a>. - </li> -<!-- TODO: Full list of permissions (or link to that list), - and how they break down by functional area]--> +<h4 id="check-platform">Check what platform the app is running on</h4> - <li>If the permission is not already granted to the app, the app calls - <a href= - "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)"> - <code>requestPermissions()</code></a> to request the - appropriate permission or permissions. This method functions - asynchronously. - <!-- TODO: insert code snippet showing permission check and request --> - </li> +<p> + This permissions model is only supported on devices running the M Developer + Preview. Before calling any of these methods, the app should verify + what platform it's running on + by checking the value of {@link android.os.Build.VERSION#CODENAME + Build.VERSION.CODENAME}. If the device is running the M Developer Preview, + {@link android.os.Build.VERSION#CODENAME CODENAME} is <code>"MNC"</code>. +</p> - <li>The system presents a dialog box to the user. - <!-- TODO: insert screenshot of permissions dialog box --> - When the user responds, the system calls <a href= - "https://android-preview.googleplex.com/reference/android/app/Activity.html#onRequestPermissionsResult(int,%20java.lang.String[],%20int[])"> - <code>Activity.onRequestPermissionsResult()</code></a> with the - results; your app needs to override that method. The callback is passed the - same request code you passed to <a href= - "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)"> - <code>requestPermissions()</code></a>. - <!-- TODO: Insert code snippet of callback method --> - </li> +<h4 id="check-for-permission">Check if the app has the needed permission</h4> + +<p>When the user tries to do something that requires a permission, the app + checks to see if it currently has permission to perform this operation. To do + this, the app calls + <code>Context.checkSelfPermission(<i>permission_name</i>)</code>. The app + should perform this check even if it knows the user has already granted that + permission, + since the user can revoke an app's permissions at any time. For example, if a + user wants to use an app to take a picture, the app calls + <code>Context.checkSelfPermission(Manifest.permission.CAMERA)</code>.</p> + +<p class="table-caption" id="permission-groups"> + <strong>Table 1.</strong> Permissions and permission groups.</p> +<table> + <tr> + <th scope="col">Permission Group</th> + <th scope="col">Permissions</th> + </tr> + + <tr> + <td><code>android.permission-group.CALENDAR</code></td> + <td> + <ul> + <li> + <code>android.permission.READ_CALENDAR</code> + </li> + </ul> + <ul> + <li> + <code>android.permission.WRITE_CALENDAR</code> + </li> + </ul> + </td> + </tr> + + <tr> + <td><code>android.permission-group.CAMERA</code></td> + <td> + <ul> + <li> + <code>android.permission.CAMERA</code> + </li> + </ul> + </td> + </tr> + + <tr> + <td><code>android.permission-group.CONTACTS</code></td> + <td> + <ul> + <li> + <code>android.permission.READ_CONTACTS</code> + </li> + <li> + <code>android.permission.WRITE_CONTACTS</code> + </li> + <li> + <code>android.permission.READ_PROFILE</code> + </li> + <li> + <code>android.permission.WRITE_PROFILE</code> + </li> + </ul> + </td> + </tr> + + <tr> + <td><code>android.permission-group.LOCATION</code></td> + <td> + <ul> + <li> + <code>android.permission.ACCESS_FINE_LOCATION</code> + </li> + <li> + <code>android.permission.ACCESS_COARSE_LOCATION</code> + </li> + </ul> + </td> + </tr> + + <tr> + <td><code>android.permission-group.MICROPHONE</code></td> + <td> + <ul> + <li> + <code>android.permission.RECORD_AUDIO</code> + </li> + </ul> + </td> + </tr> + + <tr> + <td><code>android.permission-group.PHONE</code></td> + <td> + <ul> + <li> + <code>android.permission.READ_PHONE_STATE</code> + </li> + <li> + <code>android.permission.CALL_PHONE</code> + </li> + <li> + <code>android.permission.READ_CALL_LOG</code> + </li> + <li> + <code>android.permission.WRITE_CALL_LOG</code> + </li> + <li> + <code>com.android.voicemail.permission.ADD_VOICEMAIL</code> + </li> + <li> + <code>android.permission.USE_SIP</code> + </li> + <li> + <code>android.permission.PROCESS_OUTGOING_CALLS</code> + </li> + </ul> + </td> + </tr> + + <tr> + <td><code>android.permission-group.SENSORS</code></td> + <td> + <ul> + <li> + <code>android.permission.BODY_SENSORS</code> + </li> + </ul> + <ul> + <li> + <code>android.permission.USE_FINGERPRINT</code> + </li> + </ul> + </td> + </tr> + + <tr> + <td><code>android.permission-group.SMS</code></td> + <td> + <ul> + <li> + <code>android.permission.SEND_SMS</code> + </li> + <li> + <code>android.permission.RECEIVE_SMS</code> + </li> + <li> + <code>android.permission.READ_SMS</code> + </li> + <li> + <code>android.permission.RECEIVE_WAP_PUSH</code> + </li> + <li> + <code>android.permission.RECEIVE_MMS</code> + </li> + <li> + <code>android.permission.READ_CELL_BROADCASTS</code> + </li> + </ul> + </td> + </tr> + +</table> + +<h4 id="request-permissions">Request permissions if necessary</h4> + +<p>If the app doesn't already have the permission it needs, the app calls the + <code>Activity.requestPermissions(String[], int)</code> method to + request the appropriate permission or permissions. The app passes the + permission or permissions it wants, and also an integer "request code". + This method functions asynchronously: it returns right away, and after + the user responds to the dialog box, the system calls the app's callback + method with the results, passing the same "request code" that the app passed + to <code>requestPermissions()</code>.</p> + + <p>The following code code checks if the app has permission to read the + user's contacts, and requests the permission if necessary:</p> + +<pre> +if (checkSelfPermission(Manifest.permission.READ_CONTACTS) + != PackageManager.PERMISSION_GRANTED) { + requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, + MY_PERMISSIONS_REQUEST_READ_CONTACTS); + + // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an + // app-defined int constant + + return; +} +</pre> + +<h4 id="handle-response">Handle the permissions request response</h4> + +<p> + When an app requests permissions, the system presents a dialog box to the + user. When the user responds, the system invokes your app's + <code>Activity.onRequestPermissionsResult(int, String[], int[])</code> + passing it the user response. Your app needs to override that method. The + callback is passed the same request code you passed to + <code>requestPermissions()</code>. For example, if an app requests + <code>READ_CONTACTS</code> access it might have the following callback + method: +</p> - <li>If the user grants a permission, the app is given all permissions - in that functional area that are listed in the app manifest. - If the request is denied, you should take appropriate action. For - example, you might disable any menu actions that depend on this permission. +<pre> +@Override +public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + switch (requestCode) { + case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + + // permission was granted, yay! do the + // calendar task you need to do. + + } else { + + // permission denied, boo! Disable the + // functionality that depends on this permission. + } + return; + } + + // other 'switch' lines to check for other + // permissions this app might request + } +} +</pre> + + <p>If the user grants a permission, the system gives the app all permissions + that the app manifest lists for that functional area. If the user denies the + request, you should take appropriate action. For example, you might disable + any menu actions that depend on this permission. </li> -</ul> +</p> <p> When the system asks the user to grant a permission, the user has the option of telling the system not to ask for that permission again. In that case, - when an app asks for that permission with <a href= - "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)"> - <code>requestPermissions()</code></a>, the - system immediately denies the request. For this reason, your app cannot - assume that any direct interaction with the user has taken place. + when an app uses <code>requestPermissions()</code> to ask for that permission, + the system immediately denies the request. In this case, the system calls + your <code>onRequestPermissionsResult()</code> the same way it would if the + user had explicitly rejected your request again. For this reason, your app + cannot assume that any direct interaction with the user has taken place. </p> +<h2 id="testing">Testing Runtime Permissions</h2> + + <p> - If your app runs on a device that has SDK 22 or lower, the app uses the old - permissions model. When the user installs the app, they are prompted to grant - all the permissions your app requests in its manifest, except for those - permissions which are labeled with <code><uses-permission-sdk-m></code>. + If your app targets the M Developer Preview, you must test that it + handles permissions properly. You cannot assume that your app has any + particular permissions when it runs. When the app is first launched, it is + likely to have no permissions, and the user can revoke or restore permissions + at any time. +</p> + +<p> + You should test your app to make sure it behaves properly under all + permission situations. With the M Preview SDK, we have provided new + <a href="{@docRoot}tools/help/adb.html">Android + Debug Bridge (adb)</a> commands to enable you to test your app with whatever + permissions settings you need to try. +</p> + +<h3> + New adb commands and options +</h3> + +<p> + The M Preview SDK Platform-tools provides several new commands to let you test + how your app handles permissions. +</p> + +<h4> + Install with permissions +</h4> + +<p> + You can use the <a href="{@docRoot}tools/help/adb.html#move"><code>adb + install</code></a> command's new <code>-g</code> option, which installs the + app and grants all permissions listed in its manifest: </p> -<h2 id="">Best Practices</h2> +<pre class="no-pretty-print"> +$ adb install -g <path_to_apk> +</pre> + +<h4> + Grant and revoke permissions +</h4> + +<p> + You can use new ADB <a href="{@docRoot}tools/help/adb.html#pm">package manager + (pm)</a> commands to grant and revoke permissions to an installed app. + This functionality can be useful for automated testing. +</p> + +<p> + To grant a permission, use the package manager's <code>grant</code> command: +</p> + +<pre class="no-pretty-print"> +$ adb pm grant <package_name> <permission_name> +</pre> + +<p> + For example, to grant the com.example.myapp package permission to record + audio, use this command: +</p> + +<pre class="no-pretty-print"> +$ adb pm grant com.example.myapp android.permission.RECORD_AUDIO +</pre> + +<p> + To revoke a permission, use the package manager's <code>revoke</code> command: +</p> + +<pre class="no-pretty-print"> +$ adb pm revoke <package_name> <permission_name> +</pre> + +<h2 id="best-practices">Best Practices</h2> <p> The new permissions model gives users a smoother experience, and makes it @@ -253,12 +714,32 @@ page.title=Android M Preview Runtime Permissions the new model. </p> -<h3> - Don't Overwhelm the User + +<h3 id="bp-what-you-need">Only ask for permissions you need</h3> + +<p> + Every time you ask for a permission, you force the user to make a decision. + If the user turns down the request, that reduces your app's functionality. + You should minimize the number of times you make these requests. +</p> + +<p> + For example, quite often your app can get needed functionality by using an + <a href="{@docRoot}guide/components/intents-filters.html">intent</a> instead + of asking for permissions. If your app needs to take pictures with the + phone's camera, your app can use a {@link + android.provider.MediaStore#ACTION_IMAGE_CAPTURE + MediaStore.ACTION_IMAGE_CAPTURE} intent. When your app executes the intent, the + system prompts the user to choose an already-installed camera app to take the + picture. +</p> + +<h3 id="bp-dont-overwhelm"> + Don't overwhelm the user </h3> <p> - If you confront the user with a lot of permissions requests at once, you may + 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> @@ -266,35 +747,30 @@ page.title=Android M Preview Runtime Permissions <p> In some cases, one or more permissions might be absolutely essential to your app. In that case, it might make sense to ask for all the permissions as soon - as the app launches. - <!-- TODO: insert screenshot of dialog box asking for several permissions --> - 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 to give permission to use the - camera. But if the same app also had a feature to share photos with the + 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 that 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 app's essential + 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> -<h3> - Explain Why You Need Permissions +<h3 id="bp-explain"> + Explain why you need permissions </h3> <p> - The permissions screen shown by the system when you call <a href= - "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)"> - <code>requestPermissions()</code></a> says what permission your app wants, - but doesn't say why you want it. 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 you call <a href= - "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)"> - <code>requestPermissions()</code></a>. + The permissions dialog shown by the system when you call + <code>requestPermissions()</code> 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 <code>requestPermissions()</code>. </p> <p> @@ -303,50 +779,17 @@ page.title=Android M Preview Runtime Permissions contain location information, and would be puzzled why their photography app wanted 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 - <a href= - "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)"> - <code>requestPermissions()</code></a>. + <code>requestPermissions()</code>. </p> <p> - As noted, one way to do this 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 demonstrate its "share photos with your contacts" - feature, then tell the user that they'll need to give permission for the app - to see the user's contacts, and <em>then</em> call <a href= - "https://android-preview.googleplex.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[],%20int)"> - <code>requestPermissions()</code></a> - to get that access. Of course, some users will want to skip the tutorial, so - you'll still need to check for and request permissions during the app's - normal operation. -</p> - -<h3> - Opt Out If Necessary -</h3> - -<p> - Until you are ready to use the new permissions model, you can opt out simply - by setting your app's <a href= - "http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#target"> - targetSdkVersion</a> to 22 or less. If you do this, the system will use the - old permissions model. When the user downloads the app, they will be prompted - to grant all the permissions listed in the manifest. -</p> - -<p> - With the M Developer Preview, users can turn off permissions for <em>any</em> - app from the app's Settings page, regardless of what SDK version the app - targets. For this reason, it's a good idea to follow the steps described in - <a href="#prompting">"Prompting for Permissions on the M Preview"</a> even if - your app doesn't fully support the new permissions model. -</p> - -<p class="note"> - <strong>Note:</strong> If a user turns off permissions for a legacy app, the system - silently disables the appropriate functionality. When the app attempts to - perform an operation that requires that permission, the operation will not - necessarily cause an exception. Instead, it might return an empty data set or - otherwise signal an error. + One way to do this 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 can 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 can then call <code>requestPermissions()</code> 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> |
