麦子学院 2017-06-28 10:58
Android学习之相机权限适配问题详解
回复:0 查看:3313
我们都知道,google
在
6.0
以后加强了应用权限的管理,我们也能通过标准的方法去申请权限,但是由于一些厂商的修改,在适配过程中我们会遇到各种各样的问题。在
6.0
之前,也可能会因为用户的一些设置导致我们无法获取权限。
6.0以下系统
·
打开系统相机常规来说不需要相机权限。但是如果手机
root
了,并且使用获得
root
权限
(
未获取
root
权限设置不起作用
)
的安全管理(如
LBE
,开启主动防御后)软件管理权限,此时就会出现一些问题。比如:在我们的软件调用系统相机拍照时,这些安全管理的软件会拦截这个请求,然后根据我们的设置(第一次请求时一般弹窗询问)允许、询问或者拒绝权限,此时如果是拒绝了,我们将无法调用系统相机!而此时如果用户勾选了记住选择并拒绝,那么我们将无法调用系统相机并且在下一次请求时没有任何提示!
·
由于扫描二维码不是常规的打开系统的相机界面,所以就算是在
6.0
以下也要判断权限,一般通过如下方法判断是否拥有相机权限
/**
*
通过尝试打开相机的方式判断有无拍照权限(在
6.0
以下使用拥有
root
权限的管理软件可以管理权限)
*
*
@return
*/
public
static boolean cameraIsCanUse() {
boolean isCanUse =
true;
Camera mCamera =
null;
try {
mCamera = Camera.open();
Camera.Parameters mParameters = mCamera.getParameters();
mCamera.setParameters(mParameters);
}
catch (
Exception e) {
isCanUse =
false;
}
if (mCamera !=
null) {
try {
mCamera.release();
}
catch (
Exception e) {
e.printStackTrace();
return isCanUse;
}
}
return isCanUse;
}
·
根据上面的代码,我们想是不是可以用来解决问题一。因为通过调用以上代码,如果无法打开相机
(
返回
false)
则说明没有了相机权限。
·
但是,在测试过程中发现,
LBE
如果开启了主动防御,能正确的控制权限,但是没有开启主动防御,任凭你怎么设置权限都是没用的,就算你在
LBE
中拒绝了相机权限但还是能打开系统相机的(也就是说没有开启主动防御这些设置是不生效的,不知道为什么还允许用户设置)!
·
而且,如果关闭了
LBE
的主动防御再去应用调用相机,虽然上面的代码会返回
false
,但是,这时候还是可以调用系统相机的!
·
综上,在
6.0
以下系统,我们可以选择这样做,在调用二维码的地方使用上述代码去判断是否能打开相机,调用系统相机界面拍照则无需判断(因为只有
root
过的手机才能拦截这个请求),如果用户
root
过,我们没法得到正确的判断,所以只能选择放弃了!
6.0及以上系统
·6.0
开始,应用中使用敏感权限需要通过用户的允许,所以,我们需要下面这样一个工具类来获取权限(直接上代码,代码中有解释):
/**
*
从
fragment
检查权限,如果传入的
fragment
是
null
,则后面请求权限时会调用
ActivityCompat
*
的方法
*
*
检查
6.0
及以上版本时,应用是否拥有某个权限,拥有则返回
true
,未拥有则再判断上次
*
用户是否拒绝过该权限的申请(拒绝过则
shouldShowRequestPermissionRationale
返回
* true——
这里有些手机如红米
(
红米
pro)
永远返回
false
*
这里的处理是弹一个对话框引导用户去应用的设置界面打开权限,返回
false
时这里执行
* requestPermissions
方法,此方法会显示系统默认的一个权限授权提示对话框,并在
* Activity
或
Fragment
的
onRequestPermissionsResult
得到回调,注意方法中的
requestCode
*
要与此处相同)
*
* @param fragment
:如果
fragment
不为
null
则调用
fragment
的方法申请权限(因为有些手机
*
上在
Fragment
调用
ActivityCompat
的 方法申请权限得不到回调,例如红米手机)
* @param activity
:用于弹出提示窗和获取权限
* @param permission
:对应的权限名称,如:
Manifest.permission.CAMERA
* @param hint
:引导用户进入设置界面对话框的提示文字
* @param requestCode
:请求码,对应
Activity
或
Fragment
的
onRequestPermissionsResult
*
方法的
requestCode
* @return
:
true-
拥有对应的权限
false
:未拥有对应的权限
*/
public
static boolean checkPermission(Fragment fragment,
final Activity activity, String permission,
String hint, int requestCode) {
//
检查权限
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
//
显示我们自定义的一个窗口引导用户开启权限
showPermissionSettingDialog(activity, hint);
}
else {
//
申请权限
if (fragment ==
null) {
ActivityCompat.requestPermissions(activity,
new String[]{permission},
requestCode);
}
else {
fragment.requestPermissions(
new String[]{permission},
requestCode);
}
}
return
false;
}
else { //
已经拥有权限
return
true;
}
}
·
通过注释我们也可以看到,在一些手机上如果按照
google
的写法,也会出现一些问题。但是在测试过程中使用模拟器并没有出现这样的问题。
·
问题
1
:在模拟器上,无论在
activity
还是
Fragment
中,调用
ActivityCompat.requestPermissions
去申请权限都能得到回调。而在小米手机上,如果在
Fragment
中调用申请权限的方法,必须使用
Fragment
的
requestPermissions
方法去申请权限才能在
Fragment
中得到回调。由于没有条件,所以只测试了红米手机
(
红米
pro)
,其他手机暂时不清楚!
·
问题
2
:在小米上,
shouldShowRequestPermissionRationale
始终返回
false
·
问题
3
:在应用运行的过程中,如果去系统的设置里面关闭了应用的某个权限,再回来应用时会闪退(前提是前面这个权限是使用过的)!可以参考我的另一篇文章解决:
http://www.jianshu.com/p/8c08080220f1
,测试过程发现,QQ
运行过程中,在设置界面手动关闭了他的某个界面,他竟不会重启,而且毫无卡顿,虽然微信没有显式的重启,但是在恢复界面过程中会有明显的卡顿,而支付宝则直接重启应用!
来源:简书