Android权限机制的变化.主要以Android 6.0为分水岭.关于Android的权限机制变化的文章,网上的博客很多,我这里对自己开发过程中遇到的情况,进行的整理和分类,主要根据targetSdkVersion和Build.VERSION.SDK_INT的区别区分三种情况:
环境: Build.VERSION.SDK_INT >=23 并且应用targetSdkVersion >= 23
检查相机权限: 使用方法 ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA);
博客上的很多大神都有分析,大伙可以查看下面几篇文章:
http://blog.csdn.net/lmj623565791/article/details/50709663
http://www.jianshu.com/p/dbe4d37731e6/
2. Android 6.0运行权限
环境:Build.VERSION.SDK_INT >=23 并且应用targetSdkVersion <23
注意:这里和上面的环境区别是:这里环境是在6.0以上的手机上运行,但是应用的targetSdkVersion是小于6.0的,
这就认定为该应用是旧版的应用,虽然还是在6.0以上的手机上运行,当我们这个时候使用下面方法再检查权限时就失效了:
检查相机权限: 方法失效 ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA);
可是Android6.0以上的手机,在设置中心的权限管理是可以手动修改应用的权限的,如果用户手动禁止了应用权限,特别是dangerous 权限,
如果我们不做检查判断处理的话,除了不能正常运行,而且应用在很多手机上会直接咔嚓掉.崩溃了怎么办.
这个时候就得使用方法: PermissionChecker.checkSelfPermission(context, permission);
3. Android 6.0以下的权限管理
环境:Build.VERSION.SDK_INT< 23 并且应用targetSdkVersion <23
本来原生的系统,在6.0以前我们在Manifest配置的权限都是默认打开的,在6.0以后是默认关闭的;
这个6.0是指项目的targetSdkVersion>=23,而且运行在6.0以上的手机上.其他的都被认定为6.0以下的权限管理.
/**
* 反射调用系统权限,判断权限是否打开
*
* @param permissionCode 相应的权限所对应的code
* @see {@link AppOpsManager }
*/
private int checkPermission(int permissionCode) {
int checkPermission = 0;
if (Build.VERSION.SDK_INT >= 19) {
AppOpsManager _manager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
try {
Class>[] types = new Class[]{int.class, int.class, String.class};
Object[] args = new Object[]{permissionCode, Binder.getCallingUid(), mContext.getPackageName()};
Method method = _manager.getClass().getDeclaredMethod("checkOp", types);
method.setAccessible(true);
Object _o = method.invoke(_manager, args);
Log.e(TAG, "_o:" + _o);
if ((_o instanceof Integer)) {
checkPermission = (Integer) _o;
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
checkPermission = 0;
}
return checkPermission;
}
可是怎么办,对于手机管家的改变我无能为力,最后只能妥协,换了一种方式,使用try catch,以及分贝的处理,对需要的权限进行检测,然后在捕捉到的异常中进行弹窗处理.
/**
* 检查6.0以下语音权限
*/
public boolean CheckRecordPermission(Context context) {
//通过反射系列,可以检测出小米3c系列
if (1 == checkPermission(RECORD_PERMISSION_CODE, context)) {
return false;
}
initAudioRecord();
try {
mAudioRecord.startRecording();
} catch (IllegalStateException e) {
//通过try catch,可以检测出联想,三星系列
releaseRecord();
return false;
}
if (mAudioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
//检测出联想,三星系列
releaseRecord();
return false;
}
int readSize = mAudioRecord.read(buffer, 0, buffer.length);
//通过语音分贝可以检测出华为,oppo系列
if (readSize <= 0) {
releaseRecord();
return false;
} else {
releaseRecord();
return true;
}
}
最后发现这样处理,好算友好,基本适配所有机型,当然可能也有一些特定的手机无法支持
当然我这里要解释的是:
这针对6.0以下的无奈处理...
如果在6.0以上的情况,只做这种捕捉异常的方式是不行的,如果不做check()处理,程序就会出现异常的.
点击下载工具类源码