Marshmallow Runtime Permissions
从 Android 6.0 (API 23) 开始系统开始将应用权限收紧,将权限分为普通(Normal Permissions)权限与危险权限(Dangerous Permissions)。
普通权限不会影响到用户的隐私,只要像以往那样在 manifest 中声明即可使用。
危险权限不仅要在 manifest 中声明,而且需要获得用户的批准。虽然可以临时将 target API 设置在 23 以下规避,但一来用户仍然可以在系统设置中强制拒绝授予权限造成应用崩溃,二来也并非长久之计。
危险权限及分组
系统分组处理危险权限的授予,如果应用已经获得某个组内的某项权限,那么也就默认获得了该组内的其他权限。比如我们已经获得了 READ_CONTACTS 权限,那么相当于 CONTACTS 组内的 WRITE_CONTACTS 和 GET_ACCOUNTS 权限也获得了。
| Permission Group | Permissions | 
|---|---|
| CALENDAR | READ_CALENDAR WRITE_CALENDAR  | 
| CAMERA | CAMERA | 
| CONTACTS | READ_CONTACTS WRITE_CONTACTS GET_ACCOUNTS  | 
| LOCATION | ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION  | 
| MICROPHONE | RECORD_AUDIO | 
| PHONE | READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS  | 
| SENSORS | BODY_SENSORS | 
| SMS | SEND_SMS RECEIVE_SMS READ_SMS RECEIVE_WAP_PUSH RECEIVE_MMS  | 
| STORAGE | READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE  | 
基本 API 使用
与运行时权限相关的 API 主要有以下几个方法。
1  | // Context/ContextCompat  | 
checkSelfPermission 方法用来检测是否已经获得某项权限,返回结果为PackageManager.PERMISSION_GRANTED 或 PackageManager.PERMISSION_DENIED 。
shouldShowRequestPermissionRationale 表示应用是否应该向用户解释为何需要权限。未请求过该权限时返回 false。
requestPermissions 执行请求权限的实际操作,在调用该方法时,系统弹出对话框让用户选择是否允许获取所请求的权限。
如果用户选择了 Never ask again 并拒绝授予,那么之后调用 requestPermissions 请求该权限直接会被拒绝,shouldShowRequestPermissionRationale 都会返回 false。
onRequestPermissionsResult 方法是 Activity 的一个回调方法,类似于 onActivityResult,返回权限请求的结果。
例子
1  | if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {  |