Android M Permissions 权限管理

时间:2021-11-21 15:18:44

Permissions

The M Developer Preview introduces a newapp permissions model which streamlines the process for users to install andupgrade apps. If an app running on the M Preview supports the new permissionsmodel, the user does not have to grant any permissions when they install orupgrade the app. Instead, the app requests permissions as it needs them, andthe system shows a dialog to the user asking for the permission.

VIDEO

Google I/O 2015—Android

M Permissions: Best

Practices for Developers






If an appsupports the new permissions model, it can still be installed and run ondevices running older versions of Android, using the old permissions model onthose devices.

 Overview

With the M Developer Preview, the platformintroduces a new app permissions model. Here's a summary of the key componentsof this new model:

Declaring Permissions:The app declares all the permissions it needs in the manifest, as in earlierAndroid platforms.

Permission Groups:Permissions are divided intopermissiongroups, based on their functionality. For example, the CONTACTS permission group contains permissions to read and write the user'scontacts and profile information.

Limited Permissions Grantedat Install Time: When the user installs or updates the app, the systemgrants the app all permissions listed in the manifest that fall underPROTECTION_NORMAL. For example, alarm clock and internet permissions fall underPROTECTION_NORMAL, so they are automatically granted at install time. For moreinformation about how normal permissions are handled, seeNormal Permissions.

The system mayalso grant the app signature permissions, as described inSystem components and signature permissions. The user isnot promptedto grant any permissions at install time.

User Grants Permissions atRun-Time: When the app requests a permission, the system shows a dialog tothe user, then calls the app's callback function to notify it whether the usergranted the permission.

This permission model changes the way yourapp behaves for features that require permissions. Here's a summary of thedevelopment practices you should follow to adjust to this model:

Always Check for Permissions:When the app needs to perform any action that requires a permission, it shouldfirst check whether it has that permission already. If it does not, it requeststo be granted that permission. You do not need to check for permissions thatfall under PROTECTION_NORMAL.

Handle Lack of PermissionsGracefully:If the app is not granted an appropriate permission, it shouldhandle the failure cleanly. For example, if the permission is just needed foran added feature, the app can disable that feature. If the permission isessential for the app to function, the app might disable all its functionalityand inform the user that they need to grant that permission.

Figure 1. Permission screen in the app'sSettings.

Permissions are Revocable:Users can revoke an app's permissions at any time. If a user turns off an app'spermissions, the app isnot notified.Once again, your app should verify that it has needed permissions beforeperforming any restricted actions.

Note: If an app targetsthe M Developer Preview, itmust usethe new permissions model.

As of the launch of the M DeveloperPreview, not all Google apps fully implement the new permissions model. Googleis updating these apps over the course of the M Developer Preview to properlyrespect Permissions toggle settings.

Note: If your app has its own API surface, do not proxy permissionswithout first ensuring the caller has the requisite permissions to access thatdata.

Permission groups

Related permissions are divided intopermission groups to allow users togrant related permissions to an app in a single action. The user only has togrant permission once per app for each permission group. If the appsubsequently requests a permission from the same permission group, the systemautomatically grants the permission without any action from the user. Thesystem calls your app'sonRequestPermissionsResult() method just as if the user had granted permission through thedialog box.

For example,suppose an app lists in its manifest that it needs theSEND_SMS and RECEIVE_SMS permissions, which bothbelong toandroid.permission-group.SMS. When theapp needs to send a message, it requests the

SEND_SMS permission. The system shows the user a dialog box asking if theapp can have access to SMS. If the

user agrees, the system grants the app theSEND_SMS permission it requested. Later, the app requests

RECEIVE_SMS. The system automatically grants this permission, since the userhad already approved a permission in the same permission group.

System components and signature permissions

Ordinarily, when the user installs an app,the system only grants the app the permissions listed in the manifest that fallunderPROTECTION_NORMAL. However, under somecircumstances the system grants the app more permissions:

System components automatically receive allthe permissions listed in their manifests.

If the app requests permissions in themanifest that fall underPROTECTION_SIGNATURE, and the app is signed with the same certificate as the app thatdeclared those permissions, the system grants the requesting app thosepermissions on installation. Apps cannot request signature permissions atruntime.

Forwards and backwards compatibility

If an app does not target the M DeveloperPreview, the app continues to use the old permissions model even on M Previewdevices. When the user installs the app, the system asks the user to grant allpermissions listed in the app's manifest.

Note: On devices running the M Developer Preview, a user can turn offpermissions 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 disablesthe appropriate functionality. When the app attempts to perform an operationthat requires that permission, the operation will not necessarily cause anexception. Instead, it might return an empty data set, signal an error, orotherwise exhibit unexpected behavior. For example, if you query a calendarwithout permission, the method returns an empty data set.

If you install an app using the newpermissions model on a device that is not running the M Preview, the systemtreats it the same as any other app: the system asks the user to grant alldeclared permissions at install time.

Note: For the preview release, you must set the minimum SDK version tothe M Preview SDK to compile with the preview SDK. This means you will not beable to test such apps on older platforms during the developer preview.

Permissions versus intents

In many cases, you can choose between twoways for your app to perform a task. You can have your app ask for permissionto perform the operation itself. Alternatively, you can have the app use anintent to have another app perform the task.

For example, supposeyour app needs to be able to take pictures with the device camera. Your app canrequest theandroid.permission.CAMERA permission,which allows your app to access the camera directly. Your app would

then use the camera APIs to control thecamera and take a picture. This approach gives your app full control over thephotography process, and lets you incorporate the camera UI into your app.

However, if you don't need such control, you can just use anACTION_IMAGE_CAPTURE intent to request an image. When you start the intent, the user isprompted 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 yourapp's onActivityResult() method.

Similarly, if you need to make a phonecall, access the user's contacts, and so on, you can do that by creating anappropriate intent, or you can request the permission and access theappropriate objects directly. There are advantages and disadvantages to eachapproach.

If you use permissions:

Your app has full control over the user experience when you performthe operation. However, such broad control adds to the complexity of your task,since you need to design an appropriate UI.

The user is prompted to give permission once, the first time youperform the operation. After that, your app can perform the operation withoutrequiring additional interaction from the user. However, if the user doesn'tgrant the permission (or revokes it later on), your app becomes unable toperform the operation at all.

If you use an intent:

You do not have to design the UI for the operation. The app thathandles the intent provides the UI. However, this means you have no controlover the user experience. The user could be interacting with an app you'venever seen.

If the user does not have a default app for the operation, thesystem prompts the user to choose an app. If the user does not designate adefault handler, they may have to go through an extra dialog every time theyperform the operation.

Coding for Runtime Permissions

If your app targets the new M DeveloperPreview, you must use the new permissions model. This means that in addition todeclaring your needed permissions in the manifest, you must also check to seeif you have the permissions at run time, and request the permissions if you donot already have them.

Enabling the new permissions model

To enable the new M Developer Previewpermissions model, set the app'stargetSdkVersion attribute to "MNC", and compileSdkVersion to "android-MNC". Doing so enables all the new permissions features.

For the preview release, you must setminSdkVersion to "MNC" to compile with thepreview SDK.

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 onlyneeded on the M Developer Preview. If you declare a permission this way, thenwhenever the app is installed on an older device, the system does not promptthe user or grant the permission to the app. By using the <usespermission-sdk-m> element, you can add new permissions to updated versions of yourapp without forcing users to grant permissions when they install the update.

If the app is running on a device with the M Developer Preview,<uses-permission-sdk-m> behaves the same as

<uses-permission>. The system does not prompt the user to grant any permissions whenthey install the app, and the app requests permissions as they are needed.

Promptingfor permissions

If your app uses the new M DeveloperPreview permissions model, the user is not asked to grant all permissions whenthe app is first launched on a device running the M Preview. Instead, your apprequests permissions as they are needed. When your app requests a permission,the system shows a dialog to the user.

If your app runs on a devicethat has SDK 22 or lower, the app uses the old permissions model. When the userinstalls the app, they are prompted to grant all the permissions your apprequests in its manifest, except for those permissions which are labeled with <uses-permission-sdk-m>. Check what platform the app is running on

This permissions model is only supported ondevices 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 ofBuild.VERSION.CODENAME. If the device is running the M Developer Preview,CODENAME is "MNC".

Alternatively, you can use the new methodsintroduced with revision 23 of the v4 and v13 support libraries. The supportlibrary methods behave appropriately whether or not the app is running on the MDeveloper Preview. For more information, see Support library methods for handling permissions.

Check if the app has the needed permission

When the usertries to do something that requires a permission, the app checks to see if itcurrently has permission to perform this operation. To do this, the app callscheckSelfPermission(). The app should perform this check even if it knows the user hasalready granted that permission, since the user can revoke an app's permissionsat any time.

For example, if a user wants to use an app to take a picture, theapp calls

Context.checkSelfPermission(Manifest.permission.CAMERA).

Table 1. Permissions and permission groups.

Permission Group

Permissions

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

android.permission-group.LOCATION

android.permission.ACCESS_FINE_LOCATION android.permission.ACCESS_COARSE_LOCATION

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

android.permission-group.STORAGE

android.permission.READ_EXTERNAL_STORAGE android.permission.WRITE_EXTERNAL_STORAGE

Explain why the app needs permissions

In some circumstances, you might want tohelp the user understand why your app needs a permission. For example, if auser launches a photography app, the user probably won't be surprised that theapp asks for permission to use the camera. But if the user turns down thatpermission request, then launches the photography app again, that mightindicate that the user needs some help understanding why the permission isneeded.

To help find thesituations where you need to provide extra explanation, the system provides theshouldShowRequestPermissionRationale()method. This method returnstrue if the app has requested this

permission previously and the user deniedthe request. That indicates that you should probably explain to the user whyyou need the permission.

If the user turned down the permissionrequest in the past and chose theDon'task again option in the permission request system dialog, this methodreturnsfalse. The method also returns false if the device policy prohibits the app from having that permission.

Request permissions if necessary

If the app doesn't already have thepermission it needs, the app calls therequestPermissions() method to request the appropriate permission or permissions. Theapp passes the permission or permissions it wants, and also an integer"request code". This method functions asynchronously: it returnsright away, and after the user responds to the dialog box, the system calls theapp's callback method with the results, passing the same "requestcode" that the app passed torequestPermissions().

The followingcode checks if the app has permission to read the user's contacts, and requeststhe permission if necessary:

if(checkSelfPermission(Manifest.permission.READ_CONTACTS)

       !=PackageManager.PERMISSION_GRANTED){

    // Should we show anexplanation?

   if(shouldShowRequestPermissionRationale(

            Manifest.permission.READ_CONTACTS)){

       // Explain to the user why we need to read the contacts    }

   requestPermissions(newString[]{Manifest.permission.READ_CONTACTS},

           MY_PERMISSIONS_REQUEST_READ_CONTACTS);

   // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an

    // app-defined intconstant

   return;

}

Note: When your app callsthe framework'srequestPermissions() method, the systemshows a standard dialog box to the user. Your appcannot configure or alter that dialog box. If you need to provideany information or explanation to the user, you should do thatbefore you call requestPermissions(), as described inExplainwhy the app needs permissions.

Handle the permissions request response

When an apprequests permissions, the system presents a dialog box to the user. When theuser responds, the system invokes your app'sonRequestPermissionsResult(int,String[], int[]) passing it the user response. Your appneeds to override that method. The callback is passed the same request code youpassed torequestPermissions(). For example, if anapp requestsREAD_CONTACTS access it might have thefollowing

callback method:

@Override

publicvoid 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 denies a permission request, your app should takeappropriate action. For example, your app might show a dialog explaining why itcould not perform the user's original request.

When thesystem asks the user to grant a permission, the user has the option of tellingthe system not to ask for that permission again. In that case, when an app usesrequestPermissions() to ask for thatpermission, the system immediately denies the request. In this case, the systemcalls youronRequestPermissionsResult() the sameway it would if the user had explicitly rejected your request again. For thisreason, your app cannot assume that any direct interaction with the user hastaken place.

Testing Runtime Permissions

If your app targets the M DeveloperPreview, you must test that it handles permissions properly. You cannot assumethat your app has any particular permissions when it runs. When the app isfirst launched, it is likely to have no permissions, and the user can revoke orrestore permissions at any time.

You should test your app to make sure itbehaves properly under all permission situations. With the M Preview SDK, wehave provided newAndroid DebugBridge (adb) commands to enable you to test your appwith whatever permissions settings you need to try.

New adb commands and options

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

Install with permissions

You can usethe adb install command's new -g option, which installs the app and grants all permissions listed inits 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. Thisfunctionality can be useful for automated testing.

To grant apermission, use the package manager's grant command:

$ adb shell pm grant<package_name> < permission_name>

For example, togrant the com.example.myapp package permission to record audio, use thiscommand:

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

To revoke a permission, use the package manager's 

revoke command:

$ adb shell pm revoke <package_name> < p

ermission_name>


Best Practices and Usage Notes

The new permissions model gives users asmoother experience, and makes it easier for them to install apps and feelcomfortable with what the apps are doing. We recommend the following bestpractices to take full advantage of the new model.

Only ask for permissions you need

Every time you ask for a permission, youforce the user to make a decision. If the user turns down the request, thatreduces your app's functionality. You should minimize the number of times youmake these requests.

For example,quite often your app can get needed functionality by using anintent instead ofasking for permissions. If your app needs to take pictures with the phone'scamera, your app can use a

MediaStore.ACTION_IMAGE_CAPTURE intent. When your app executes the intent, the system prompts theuser to choose an already-installed camera app to take the picture.

Don't overwhelm the user

If you confront the user with a lot ofrequests for permissions at once, you may overwhelm the user and cause them toquit your app. Instead, you should ask for permissions as you need them.

In some cases, one or more permissionsmight be absolutely essential to your app. In that case, it might make sense toask for all the permissions as soon as the app launches. For example, if youmake a photography app, the app would need access to the device camera. Whenthe user launches the app for the first time, they won't be surprised to beasked for permission to use the camera. But if the same app also had a featureto share photos with the user's contacts, you probably should not ask for that permission at firstlaunch. Instead, wait until the user tries to use the "sharing"feature and ask for the permission then.

If your app provides a tutorial, it maymake sense to request the app's essential permissions at the end of thetutorial sequence.

Explain why you need permissions

The permissions dialog shown by the systemwhen you callrequestPermissions() says whatpermission your app wants, but doesn't say why. In some cases, the user mayfind that puzzling. It's a good idea to explain to the user why your app wantsthe permissions before callingrequestPermissions().

For example, aphotography app might want to use location services, so it can geotag thephotos. A typical user might not understand that a photo can contain locationinformation, and would be puzzled why their photography app wanted to know thelocation. So in this case, it's a good idea for the app to tell the user aboutthis featurebefore

calling requestPermissions().

One way to do this is to incorporate these requests into an apptutorial. The tutorial can show each of the app's features in turn, and as itdoes this, it can explain what permissions are needed. For example, thephotography app's tutorial can demonstrate its "share photos with yourcontacts" feature, then tell the user that they need to give permissionfor the app to see the user's contacts. The app can then callrequestPermissions() to ask the user for that access. Of course, not every user is goingto follow the tutorial, so you still need to check for and request permissionsduring the app's normal operation.

Support library methods for handling permissions

Revision 23 of the v4 and v13 supportlibraries provide several new methods for managing permissions. The supportlibrary methods work properly on any device that can use those libraries. Thus,if you use the support library methods, you do not need to check whether yourapp is running on a device with the M Developer Preview. If an app is installedon a device running the M Preview, the support library methods behave the sameas their framework equivalents. If the device is running an earlier version ofAndroid, the methods behave appropriately, as described below.

The v4 supportlibrary provides the following permissions methods:

ContextCompat.checkSelfPermission()

Returns PERMISSION_GRANTED if the app has the specified permission, whether or not the deviceis using the M Preview. If the app does not have the specified permission,returnsPERMISSION_DENIED.

ActivityCompat.requestPermissions()

If the device is notrunning the M Preview, invokes the callback method in

ActivityCompat.OnRequestPermissionsResultCallback. PassesPERMISSION_GRANTED if the app alreadyhas the specified permission, orPERMISSION_DENIED if it does not.

ActivityCompat.shouldShowRequestPermissionRationale()

If the deviceis not running the M Preview, always returnsfalse.

The v4 supportlibrary also contains thePermissionChecker class, which provides several static utility methods for apps thatuse IPC to provide services for other apps. For example,

PermissionChecker.checkCallingPermission() checks whether an IPC made by a particular package has a specifiedpermission.

Note: If your app acts on behalf of third-party apps to call platformmethods that require runtime permissions on behalf of a third-party app, youshould use the appropriatePermissionChecker methods to ensure that the other app is allowed to perform theoperation. The platform has a compatibility mode that allows users to revoke alegacy app's access to permission-protected methods. If the user revokes accessin compatibility mode the app's permissions are not actually revoked; instead,access to the APIs is restricted. ThePermissionChecker methods verify app permissions in both normal and legacy modes.

The v13support library provides the following permissions methods:

FragmentCompat.requestPermissions()

If the device is notrunning the M Preview, invokes the callback method in

FragmentCompat.OnRequestPermissionsResultCallback. PassesPERMISSION_GRANTED if the app alreadyhas the specified permission, orPERMISSION_DENIED if it does not.

FragmentCompat.shouldShowRequestPermissionRationale()

Ifthe device is not running the M Preview, always returnsfalse.

Normal permissions

Many permissions are designated as PROTECTION_NORMAL, which indicates that there's no great risk to the user's privacyor security in letting apps have those permissions. For example, users wouldreasonably want to know whether an app can read their contact information, sousers have to grant this permission explicitly. By contrast, there's no greatrisk in allowing an app to vibrate the device, so that permission is designatedasnormal.

If an app declares in its manifest that itneeds a normal permission, the system automatically grants the app thatpermission at install time. The system does not prompt the user to grant normalpermissions, and users cannot revoke these permissions.

Ifyour app declares that it needs normal permissions, the app does not need tocallcheckSelfPermission() or requestPermissions() for those permissions. Since you declared the permissions in themanifest, you can be

sure your app was granted those permissionsat install time.

Currently, the following permissions areclassified asPROTECTION_NORMAL:

android.permission.ACCESS_LOCATION_EXTRA_COMMANDS

android.permission.ACCESS_NETWORK_STATE

android.permission.ACCESS_NOTIFICATION_POLICY

android.permission.ACCESS_WIFI_STATE

android.permission.ACCESS_WIMAX_STATE

android.permission.BLUETOOTH

android.permission.BLUETOOTH_ADMIN

android.permission.BROADCAST_STICKY

android.permission.CHANGE_NETWORK_STATE

android.permission.CHANGE_WIFI_MULTICAST_STATE

android.permission.CHANGE_WIFI_STATE

android.permission.CHANGE_WIMAX_STATE

android.permission.DISABLE_KEYGUARD

android.permission.EXPAND_STATUS_BAR

android.permission.FLASHLIGHT

android.permission.GET_PACKAGE_SIZE

android.permission.INTERNET

android.permission.KILL_BACKGROUND_PROCESSES

android.permission.MODIFY_AUDIO_SETTINGS

android.permission.NFC

android.permission.READ_SYNC_SETTINGS

android.permission.READ_SYNC_STATS

android.permission.RECEIVE_BOOT_COMPLETED

android.permission.REORDER_TASKS

android.permission.REQUEST_INSTALL_PACKAGES

android.permission.SET_TIME_ZONE

android.permission.SET_WALLPAPER

android.permission.SET_WALLPAPER_HINTS

android.permission.SUBSCRIBED_FEEDS_READ

android.permission.TRANSMIT_IR

android.permission.USE_FINGERPRINT

android.permission.VIBRATE

android.permission.WAKE_LOCK

android.permission.WRITE_SYNC_SETTINGS

com.android.alarm.permission.SET_ALARM

com.android.launcher.permission.INSTALL_SHORTCUT

com.android.launcher.permission.UNINSTALL_SHORTCUT