diff --git a/docs/html/preview/features/images/app-permissions-screen.png b/docs/html/preview/features/images/app-permissions-screen.png new file mode 100644 index 0000000000000..679b7ad6d78b0 Binary files /dev/null and b/docs/html/preview/features/images/app-permissions-screen.png differ diff --git a/docs/html/preview/features/images/app-permissions-screen@2x.png b/docs/html/preview/features/images/app-permissions-screen@2x.png new file mode 100644 index 0000000000000..e3eb13fa77ba0 Binary files /dev/null and b/docs/html/preview/features/images/app-permissions-screen@2x.png differ diff --git a/docs/html/preview/features/runtime-permissions.jd b/docs/html/preview/features/runtime-permissions.jd index 4a0101089d4db..f9646a8b35cb5 100644 --- a/docs/html/preview/features/runtime-permissions.jd +++ b/docs/html/preview/features/runtime-permissions.jd @@ -1,15 +1,52 @@ -page.title=Android M Preview Runtime Permissions +page.title=Runtime Permissions @jd:body +
+
+

Quickview

+ + +

In this document

+
    +
  1. Overview
  2. +
  3. Coding for Runtime Permissions
  4. +
  5. Testing Runtime Permissions
  6. +
  7. Best Practices
  8. +
+ + + + +
+
+ +

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

@@ -18,70 +55,122 @@ page.title=Android M Preview Runtime Permissions model on those devices.

-

+

Overview

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

+ +

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

+ + -

- System Apps and Signature Permissions +

+ Note: If an app targets the M Developer Preview, it + must use the new permissions model. +

+ +

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

+ +

+ Note: 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. +

+ +

+ System apps and signature permissions

- Ordinarily, an app is just granted the - PROTECTION_NORMAL 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:

In both cases, the user can still revoke permissions at any time by going to - the app's Settings screen, so the app should continue to check for - permissions at run time and request them if necessary. + the system's Settings screen and choosing Apps + > app_name > Permissions. The app + should continue to check for permissions at run time and request them if + necessary.

-

- Forwards and Backwards Compatibility +

+ Forwards and backwards compatibility

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

+ +

+ Note: 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.

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

-

Coding for Runtime Permissions

+

+ Note: 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. +

+ +

Permissions versus intents

+ +

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

+ +

+ For example, suppose your app needs to be able to take pictures with the + device camera. Your app can request the + android.permission.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. +

+ +

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

+ +

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

+ +

+ If you use permissions: +

+ + + +

+ If you use an intent: +

+ + + +

Coding for Runtime Permissions

If your app targets the new M Developer Preview, you must use the new @@ -129,44 +311,47 @@ page.title=Android M Preview Runtime Permissions have them.

-

- Enabling the New Permissions Model +

+ Enabling the new permissions model

To enable the new M Developer Preview permissions model, set the app's - - targetSdkVersion attribute to "M". Doing this enables all the new - permissions features. + targetSdkVersion attribute to "MNC", and + compileSdkVersion to "android-MNC". Doing so + enables all the new permissions features.

- +

+ For the preview release, you must set minSdkVersion to + "MNC" to compile with the preview SDK. +

-

- Designating a Permission for M Only +

+ Designating a permission for the M Preview only

- You can use the new <uses-permission-sdk-m> 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 <uses-permission-sdk-m> 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 <uses-permission-sdk-m> + element, you can add new permissions to updated versions of your app without forcing users to grant permissions when they install the update.

- 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, <uses-permission-sdk-m> behaves the same as - <uses-permission>. The user is not prompted to grant any - permissions when the app is installed, and the app requests permissions as - they are needed. + <uses-permission>. + 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.

- Prompting for Permissions on the M Preview + Prompting for permissions

@@ -177,66 +362,6 @@ page.title=Android M Preview Runtime Permissions user.

-

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

-
    -
  1. 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 - Context.CheckSelfPermission(permission_name) . 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 - Context.CheckSelfPermission(Manifest.permission.CAMERA). -
  2. - - - -
  3. If the permission is not already granted to the app, the app calls - - requestPermissions() to request the - appropriate permission or permissions. This method functions - asynchronously. - -
  4. - -
  5. The system presents a dialog box to the user. - - When the user responds, the system calls - Activity.onRequestPermissionsResult() with the - results; your app needs to override that method. The callback is passed the - same request code you passed to - requestPermissions(). - -
  6. - -
  7. 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. -
  8. - - -

    - 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 - requestPermissions(), the - system immediately denies the request. For this reason, your app cannot - assume that any direct interaction with the user has taken place. -

    -

    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 @@ -244,7 +369,342 @@ page.title=Android M Preview Runtime Permissions permissions which are labeled with <uses-permission-sdk-m>.

    -

    Best Practices

    +

    Check what platform the app is running on

    + +

    + 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 "MNC". +

    + +

    Check if the app has the needed permission

    + +

    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 + Context.checkSelfPermission(permission_name). 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 + Context.checkSelfPermission(Manifest.permission.CAMERA).

    + +

    + Table 1. Permissions and permission groups.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Permission GroupPermissions
    android.permission-group.CALENDAR +
      +
    • + android.permission.READ_CALENDAR +
    • +
    +
      +
    • + android.permission.WRITE_CALENDAR +
    • +
    +
    android.permission-group.CAMERA +
      +
    • + android.permission.CAMERA +
    • +
    +
    android.permission-group.CONTACTS +
      +
    • + android.permission.READ_CONTACTS +
    • +
    • + android.permission.WRITE_CONTACTS +
    • +
    • + android.permission.READ_PROFILE +
    • +
    • + android.permission.WRITE_PROFILE +
    • +
    +
    android.permission-group.LOCATION +
      +
    • + android.permission.ACCESS_FINE_LOCATION +
    • +
    • + android.permission.ACCESS_COARSE_LOCATION +
    • +
    +
    android.permission-group.MICROPHONE +
      +
    • + android.permission.RECORD_AUDIO +
    • +
    +
    android.permission-group.PHONE +
      +
    • + android.permission.READ_PHONE_STATE +
    • +
    • + android.permission.CALL_PHONE +
    • +
    • + android.permission.READ_CALL_LOG +
    • +
    • + android.permission.WRITE_CALL_LOG +
    • +
    • + com.android.voicemail.permission.ADD_VOICEMAIL +
    • +
    • + android.permission.USE_SIP +
    • +
    • + android.permission.PROCESS_OUTGOING_CALLS +
    • +
    +
    android.permission-group.SENSORS +
      +
    • + android.permission.BODY_SENSORS +
    • +
    +
      +
    • + android.permission.USE_FINGERPRINT +
    • +
    +
    android.permission-group.SMS +
      +
    • + android.permission.SEND_SMS +
    • +
    • + android.permission.RECEIVE_SMS +
    • +
    • + android.permission.READ_SMS +
    • +
    • + android.permission.RECEIVE_WAP_PUSH +
    • +
    • + android.permission.RECEIVE_MMS +
    • +
    • + android.permission.READ_CELL_BROADCASTS +
    • +
    +
    + +

    Request permissions if necessary

    + +

    If the app doesn't already have the permission it needs, the app calls the + Activity.requestPermissions(String[], int) 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 requestPermissions().

    + +

    The following code code checks if the app has permission to read the + user's contacts, and requests the permission if necessary:

    + +
    +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;
    +}
    +
    + +

    Handle the permissions request response

    + +

    + When an app requests permissions, the system presents a dialog box to the + user. When the user responds, the system invokes your app's + Activity.onRequestPermissionsResult(int, String[], int[]) + passing it the user response. Your app needs to override that method. The + callback is passed the same request code you passed to + requestPermissions(). For example, if an app requests + READ_CONTACTS access it might have the following callback + method: +

    + +
    +@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
    +    }
    +}
    +
    + +

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

    + +

    + 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 uses requestPermissions() to ask for that permission, + the system immediately denies the request. In this case, the system calls + your onRequestPermissionsResult() 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. +

    + +

    Testing Runtime Permissions

    + + +

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

    + +

    + You should test your app to make sure it behaves properly under all + permission situations. With the M Preview SDK, we have provided new + Android + Debug Bridge (adb) commands to enable you to test your app with whatever + permissions settings you need to try. +

    + +

    + New adb commands and options +

    + +

    + The M Preview SDK Platform-tools provides several new commands to let you test + how your app handles permissions. +

    + +

    + Install with permissions +

    + +

    + You can use the adb + install command's new -g option, which installs the + app and grants all permissions listed in its manifest: +

    + +
    +$ adb install -g <path_to_apk>
    +
    + +

    + Grant and revoke permissions +

    + +

    + You can use new ADB package manager + (pm) commands to grant and revoke permissions to an installed app. + This functionality can be useful for automated testing. +

    + +

    + To grant a permission, use the package manager's grant command: +

    + +
    +$ adb pm grant <package_name> <permission_name>
    +
    + +

    + For example, to grant the com.example.myapp package permission to record + audio, use this command: +

    + +
    +$ adb pm grant com.example.myapp android.permission.RECORD_AUDIO
    +
    + +

    + To revoke a permission, use the package manager's revoke command: +

    + +
    +$ adb pm revoke <package_name> <permission_name>
    +
    + +

    Best Practices

    The new permissions model gives users a smoother experience, and makes it @@ -253,12 +713,32 @@ page.title=Android M Preview Runtime Permissions the new model.

    -

    - Don't Overwhelm the User + +

    Only ask for permissions you need

    + +

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

    + +

    + For example, quite often your app can get needed functionality by using an + intent 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. +

    + +

    + Don't overwhelm the user

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

    @@ -266,35 +746,30 @@ page.title=Android M Preview Runtime Permissions

    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. - - 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 not ask for that permission at first launch. Instead, wait until the user tries to use the "sharing" feature and ask for the permission then.

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

    -

    - Explain Why You Need Permissions +

    + Explain why you need permissions

    - The permissions screen shown by the system when you call - requestPermissions() 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 - requestPermissions(). + The permissions dialog shown by the system when you call + 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 requestPermissions().

    @@ -303,50 +778,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 before calling - - requestPermissions(). + requestPermissions().

    - 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 then call - requestPermissions() - 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. -

    - -

    - Opt Out If Necessary -

    - -

    - Until you are ready to use the new permissions model, you can opt out simply - by setting your app's - targetSdkVersion 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. -

    - -

    - With the M Developer Preview, users can turn off permissions for any - 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 - "Prompting for Permissions on the M Preview" even if - your app doesn't fully support the new permissions model. -

    - -

    - Note: 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 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.

    diff --git a/docs/image_sources/preview/features/app-permissions-screen-orig.png b/docs/image_sources/preview/features/app-permissions-screen-orig.png new file mode 100644 index 0000000000000..1868c7a5ad88c Binary files /dev/null and b/docs/image_sources/preview/features/app-permissions-screen-orig.png differ