sky-mxc 总结 转载注明出处:https://sky-mxc.github.io
6.0 运行时权限处理
在6.0以前 权限都是在安装时授权的,如果用户不授权就无法安装;
Android从6.0(API 23)开始 使用运行时权限,而不是像以前那样安装时授权。当你需要某些权限时,系统会向用户去申请权限。用户可以随时取消授权给你的权限。
6.0中权限分为两类 普通权限和危险权限,普通权限在AndroidManifest 文件中注册就可以得到,对于能获得用户隐私的权限属于危险权限。在使用的时候必须用户授权才能使用。例如 拍照,录音 sd卡的操作,危险权限被分为很多组,只要一组中的其中一项被授权 Android 就会将这一组的权限打包都授权给你app
危险权限
危险权限被分为了9组
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
普通权限
• ACCESS_LOCATION_EXTRA_COMMANDS
• ACCESS_NETWORK_STATE
• ACCESS_NOTIFICATION_POLICY
• ACCESS_WIFI_STATE
• BLUETOOTH
• BLUETOOTH_ADMIN
• BROADCAST_STICKY
• CHANGE_NETWORK_STATE
• CHANGE_WIFI_MULTICAST_STATE
• CHANGE_WIFI_STATE
• DISABLE_KEYGUARD
• EXPAND_STATUS_BAR
• GET_PACKAGE_SIZE
• INSTALL_SHORTCUT
• INTERNET
• KILL_BACKGROUND_PROCESSES
• MODIFY_AUDIO_SETTINGS
• NFC
• READ_SYNC_SETTINGS
• READ_SYNC_STATS
• RECEIVE_BOOT_COMPLETED
• REORDER_TASKS
• REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
• REQUEST_INSTALL_PACKAGES
• SET_ALARM
• SET_TIME_ZONE
• SET_WALLPAPER
• SET_WALLPAPER_HINTS
• TRANSMIT_IR
• UNINSTALL_SHORTCUT
• USE_FINGERPRINT
• VIBRATE
• WAKE_LOCK
• WRITE_SYNC_SETTINGS
请求权限
targetSdkVerion
申请权限之前必须先说一下tartgetSdkVersion ,目标sdk版本,一般定义在build.gradle文件中。
如果 targetSDKVersion 是22 安装好之后 Android系统就知道这个App在系统API22一下都测试过了并且能正确运行的,假如这个App运行在了Android6.0系统上,Android就会对这个App很”照顾“,兼容它正确运行。6.0系统会把App申请的权限都默认给这个App。
但是 ,在6.0系统 ,用户可随时撤销授权给app的权限 ,即使系统默认都授权给你,用户也可以取消掉。这时就没权限了。所以即使是targetSDKVersion < 23 也不是就万事大吉了。Android为我们提供了android.support.v4.content.PermissionChecker 来检测是否具有某些权限判断 targetSdkVersion
1 | /** |
检查权限
在去请求权限之前 应该先检查一下系统 的版本 如果系统版本在6.0以上再去请求权限,如果不在就不去请求,直接使用
1 | /** |
PermissionChecker.checkSelfPermission() 方法就是用于检查App自身有没有某一个权限 此方法适用于 targetSdkVersion < 23
context.checkSelfPermission() 适用于 targetSDKVersion >=23
返回结果有三种 状态
- PermissionChecker.PERMISSION_GRANTED; //有权限
- PermissionChecker.PERMISSION_DENIED ; //无权限
- PermissionChecker.PERMISSION_DENIED_APP_OP;//无权限
PermissionChecker.PERMISSION_DENIED 和 PermissionChecker.PERMISSION_DENIED_APP_OP 的区别:
- targetSDKVersion 小于23没有权限就返回 PermissionChecker.PERMISSION_DENIED_APP_OP
- targetSdkVersion23或者以上的返回 PermissionChecker.PERMISSION_DENIED
1 | //检测targetSDKVersion 是否在23以上 |
请求权限
使用 requestPermissions() 方法去请求权限 参数有两个 权限数组 和请求码
1 | requestPermissions(new String[]{"android.permission.READ_SMS"},10); |
在请求权限之前最好是跟用户解释清楚为什么要使用这个权限 ,用时候用户并不清楚为什么使用权限 就会被拒绝,如果一个权限被请求一次以上 在系统申请权限的Dialog会出现一个不再提醒的复选框 那怎么判断 用户是否勾选了这个 不再提醒呢 ,Android提供了 shouldShowRequestPermissionRationale() 方法;
这个方法 在 第一次请求的时候 和 在用户勾选了不再提醒时 返回false ,其他均返回true
1 | // 第一次请求就返回false 拒绝过返回true 或者 用户选择不再提示返回false |
处理用户响应
重写 activity的 onRequestPermissionsResult() 的方法 处理权限的响应
权限的申请是可以多个权限一块申请的 ,所以 响应结果也是 数组和 请求的权限数组对应
1 | /** |
完整的短信读取权限申请 流程
请求权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 /**
* 请求短信权限
*/
(api = Build.VERSION_CODES.M)
private void requestSms() {
// 权限
final String permission = "android.permission.READ_SMS";
//检查当前系统版本是否在6.0以上
if (checkVersion()){
int result =-1;
//检测targetSDKVersion 是否在23以上
if (checkTargetSdkVersion()){
//targetSDKVersion >=23
//检查是否具有读取短信的权限
result = checkSelfPermission(permission);
}else{
//targetSDKVersion <23
//检查是否具有读取短信的权限
result= PermissionChecker.checkSelfPermission(this,permission);
}
LogCheckResult(result);
if(result==PermissionChecker.PERMISSION_GRANTED){
//已经有了权限
//TODO 读取短信
Toast.makeText(this,"读取短信授权成功",Toast.LENGTH_SHORT).show();
tv.setText(getSmsInPhone());
}else{
//没有权限
//TODO 请求权限
// 第一次请求就返回false 拒绝过返回true 或者 用户选择不再提示返回false
boolean answer= shouldShowRequestPermissionRationale(permission);
log("shouldShowRequestPermissionRationale :"+answer);
if (!answer){
new AlertDialog.Builder(this).setTitle("权限说明")
.setMessage("此功能需要读取短信的权限,没有权限无法使用此功能。请在稍后授权后使用")
.setNegativeButton("确定", new DialogInterface.OnClickListener() {
(api = Build.VERSION_CODES.M)
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[]{permission},SMS);
}
})
.setNeutralButton("取消",null)
.show();
}else{
requestPermissions(new String[]{permission},SMS);
}
}
}else{
//无需请求
Toast.makeText(this,"读取短信授权成功",Toast.LENGTH_SHORT).show();
tv.setText(getSmsInPhone());
}
}响应处理
1 |
|
短信读取 代码
1 | public String getSmsInPhone() { |
读取短信的代码参考这位大神的代码:http://blog.csdn.net/ithomer/article/details/7328321
关于这次的Demo,github 地址: https://github.com/sky-mxc/AndroidDemo/tree/master/permission