前言
众所周知,谷歌在Android 6.0提出了危险权限这个概念,让我们开发应用的时候,需要花一些时间去关注动态权限的处理.今天我就把在动态权限这块地方遇到的坑给大家说说.
我们都知道,在安卓开发中,经常需要用到几个比较常见的权限,例如:
Manifest.permission.READ_EXTERNAL_STORAGE, //储存空间权限
Manifest.permission.READ_PHONE_STATE, //手机状态权限
Manifest.permission.ACCESS_FINE_LOCATION,//位置访问权限
Manifest.permission.CAMERA //相机权限
```
我们在做动态权限适配的时候一般都需要多个权限同时进行处理,
,刚刚开始接触动态权限的时候,感觉一个权限还比较好处理,逻辑是:
第一,先判断是否获得权限
第二,如果没有,就去申请权限,处理回调方法然后执行想要的逻辑
但是多个权限,就没有我们想象的那么简单了,你需要关注到每个权限是否都已经有申请过,由于公司的APP的设计是在Splash界面需要同时获得多个权限,我必须要保证每个权限都要被获取,因此我刚刚开始的想法是这样的:
第一步, 判断权限. 遍历所有权限进行判断权限是否都被获取,得到一个是否全部获得权限的标记,通过标记判断是否需要进行权限申请。
第二步, 申请权限. 如果当中有没有获取权限的,那就需要申请权限, 在权限申请回调拿到结果, 判断没有被申请通过的权限, 存放在一个集合中, 然后再去进行单个权限申请,依然对返回值进行判断,如果不通过就成重新把未通过的权限进行申请,通过就进入程序.
这种类似于循环式的做法,看起来可行,实则漏洞百出,我似乎忽略了一种情况,那就是当用户拒绝权限并禁止访问的时候,APP会进入假死状态,一直会卡在Splash界面,后来我也在网上找了一些资料,发现shouldShowRequestPermissionRationale(String permisssion) 这个方法可以帮我解决问题,于是我逻辑是这样写的!
boolean flag=false;
for (String permission : permissions) {
if (!shouldShowRequestPermissionRationale(permission)) {
flag = true;
break;
}
}
if(flag){
//为true 就进入权限设置
}else{
//为false 表示没有被禁止询问 直接进行上述我写的逻辑(判断、申请权限等)
}
于是,我卸载重新安装应用,部署在模拟器上,一运行,出BUG了
我发现,如果我是重新安装应用,程序直接引导我去设置界面设置权限,连申请权限都不走了!我心里一万只草泥马奔腾而过,这是什么鬼?难道这个shouldShowRequestPermissionRationale()的不是关心不再询问[checkbox]的结果么?
于是我再新建一个应用进行测试,这次我转换了一下我的思路,我先用单个权限进行测试,步骤如下:
if (checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED) { //先对权限进行判断
if (shouldShowRequestPermissionRationale(permission)) {
LogUtils.d("方法返回值为true时"); //系统或人为关闭时,可以跳转到设置页面进行设置
new AlertDialog.Builder(this)
.setMessage("为了保证应用能够正常使用,请前往设置如下权限:" +
"位置访问权限、相机权限、储存空间权限")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
}
}).show();
} else {
LogUtils.d("方法返回值为false时");
requestPermissions(new String[]{permission}, REQUEST_SINGLE_PERMISSION);
}
} else {
//权限已经被申请
LogUtils.d("权限被接受");
}
原来还是因为这个方法[shouldShowRequestPermissionRationale(xxx)]导致的,当为true的时候,是表示有人为选中拒绝(被禁止询问),或者是系统默认拒绝状态(一些厂商会将底层权限设置进行修改,比如小米等),而为false时 只是表示权限没有被通过的意思.我去 ,原来网上的文章也有时候会搞错,真心尴尬。
最后,如果大家在开发中,遇到动态权限处理,最好还是用别人的框架吧,除非你时间充裕,并且想学习下动态权限其中的原理,否则 ,劝大家还是用框架,毕竟框架用起来方便,而且考虑比较全面.