自从Android6.0发布以来,在权限上做出了很大的变动,不再是之前的只要在manifest设置就可以任意获取权限,而是更加的注重用户的隐私和体验,不会再强迫用户因拒绝不该拥有的权限而导致的无法安装的事情,也不会再不征求用户授权的情况下,就可以任意的访问用户隐私,而且即使在授权之后也可以及时的更改权限。这就是6.0版本做出的更拥护和注重用户的一大体现。Google将权限分为两类,一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如开启相机、录音等。
Dangerous Permissions:
group:android.permission-group.CONTACTS//联系人
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE//电话相关
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.CALENDAR//日历
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA//相机
permission:android.permission.CAMERA
group:android.permission-group.SENSORS//传感器
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION//定位
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE//存储
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE//录音
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS//短信相关
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
危险权限分组的好处是,只要有一个权限申请成功了,就默认整组权限都可以使用了。也就是说,如果你需要申请group.SMS 下的permission:android.permission.READ_SMS,而你的app早已被用户授权了同一组的permission:android.permission.SEND_SMS,那么系统会立即授权,而不需要用户去点击授权。
ps:需要动态申请的危险权限依然需要配置到AndroidManifest.xml,不然会报错
申请步骤
1.确保你的targetSdkVersion>=23
2 在AndroidManifest.xml中申请你需要的权限
3.开始申请权限,此处分为4步。
(1)检查是否有该权限,checkSelfPermission(),如果已经开启,则直接做你想做的。这个方法没有回调,调用了,就直接告诉你,你是否拥有该权限。
ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED
(2)如果未开启,则判断是否需要向用户解释为何申请权限
shouldShowRequestPermissionRationale。
(3)如果需要(即shouldShowRequestPermissionRationale返回true),则可以弹出对话框提示用户申请权限原因,用户确认后申请权限requestPermissions();如果不需要(即返回false),则直接申请权限requestPermissions()。
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.READ_CONTACTS},
REQUEST_READ_CONTACTS);
(4) 接收权限处理结果
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
以上即是google建议的运行时权限处理过程。
各种坑
(1)系统询问对话框:有些厂商的手机系统优化的好,调用checkSelfPermission就会弹出系统询问对话框,但实际上Android原生系统中,requestPermissions才会弹出对话框
(2)回调:如果你是在Fragment中请求权限,不要使用ActivityCompat.requestPermissions, 直接使用Fragment的requestPermissions方法,否则会回调到Activity的 onRequestPermissionsResult;如果是Fragment嵌套Fragment,在子Fragment中申请权限时,子Fragment中使用requestPermissions方 法,onRequestPermissionsResult不会回调回来
(3)shouldShowRequestPermissionRationale:Android原生系统中,如果第二次弹出权限申请的对话框,会出现“以后不再弹出”的提示框,如果用户勾选了,你再申请权限,则shouldShowRequestPermissionRationale返回true,意思是说要给用户一个 解释,告诉用户为什么要这个权限。然而,在实际开发中,需要注意的是,很多手机对原生系统做了修改,比如小米,小米4的6.0的shouldShowRequestPermissionRationale 就一直返回false,而且在申请权限时,如果用户选择了拒绝,则不会再弹出对话框了。
ps:推荐大家一个动态权限的开源库Easypermissions,可以学习借鉴一下
https://github.com/googlesamples/easypermissions