1.概述
随着Android 6.0 7.0 我们开发者所要应对的主要就是新版本SDK带来的一些变化,既然是程序员那么我们肯定就特别关注开发部分的变化,其中之一就是权限处理。那么在6.0及以上版本我们的危险权限都需要在运行的时候去申请,之前都是在清单文件中配置即可,现在就不行了需要加代码申请。
2.运行时权限的检测
2.1. Android6.0之后的权限差别
对于6.0以下的权限及在安装的时候,根据权限声明产生一个权限列表,用户只有在同意之后才能完成app的安装。而在6.0以后,我们可以直接安装,当app需要权限是会给予用户提示用户可以选择同意和拒绝。 新的权限机制更好的保护了用户的隐私,Google将权限分为两类,一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、打电话等等。
下面列出 Android 中所有的危险权限,一共是9组24个权限。 权限组名 权限名称
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 ERAD_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
危险权限都是一组一组的,这是个什么概念呢?又或是有什么用呢?如果app运行在Android 6.x的机器上,对于授权机制是这样的。如果你申请某个危险的权限,假设你的app早已被用户授权了同一组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。比如你的app对READ_CONTACTS已经授权了,当你的app申请WRITE_CONTACTS时,系统会直接授权通过。此外,对于申请时弹出的dialog上面的文本说明也是对整个权限组的说明,而不是单个权限
2.2. 相关代码,以打电话为例
2.2.1.我们需要去检测该权限有没有背用户授予过,如果没有则需要申请打电话权限,如果有授予过可以直接拨打电话。
ContextCompat.checkSelfPermission:检测权限
ActivityCompat.requestPermissions:申请权限
// ContextCompat.checkSelfPermission() // 方法返回值为PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。 // 当返回GRANTED表示有该权限,DENIED表示没有该权限。
if(ContextCompat.checkSelfPermission(this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
// 没有该权限 申请打电话权限 // 三个参数 第一个参数是 Context , 第二个参数是用户需要申请的权限字符串数组,第三个参数是请求码 主要用来处理用户选择的返回结果
ActivityCompat.requestPermissions(this,new String[]{"Manifest.permission.CALL_PHONE"},CALL_PHONE_REQUEST_CODE);
}else {
// 有该权限,直接打电话
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + 137XXXXXXXX);
intent.setData(data); startActivity(intent);
}
2.2.2. 处理回调 如果用户同意或是拒绝那么会回调onRequestPermissionsResult()
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(requestCode == CALL_PHONE_REQUEST_CODE){
if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission Granted 通过 打电话
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + 137XXXXXXXX);
intent.setData(data); startActivity(intent);
} else {
// Permission Denied 被拒绝 Toast.makeText(this,"权限被拒绝了",Toast.LENGTH_SHORT).show();
}
}
}