以下用相机权限举例
1.正常机型是这样的:6.0以下不需要授权,6.0以上需要授权,需要授权的,授权以后进入正常业务逻辑,拒绝授权停留在本页面。
2.不正常机型:6.0以下由手机管家,或者安全中心之类的手机自带app进行权限拦截。
6.0以上机型,拒绝授权申请以后依然返回已经授权,此时按照正常的逻辑进入下一个页面肯定会崩溃,因为camera是空的,只要有相关的操作要执行就会异常。
发生原因:6.0以下:
camera=Camera.open(0);点进去
public static Camera open(int cameraId) { return new Camera(cameraId); }
继续点进区
Camera(int cameraId) { int err = cameraInitNormal(cameraId); if (checkInitErrors(err)) { if (err == -EACCES) { throw new RuntimeException("Fail to connect to camera service"); } else if (err == -ENODEV) { throw new RuntimeException("Camera initialization failed"); } // Should never hit this. throw new RuntimeException("Unknown camera error"); } }点进
cameraInitNormal方法中
private int cameraInitNormal(int cameraId) { return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT); }
private int cameraInitVersion(int cameraId, int halVersion) { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; Looper looper; if ((looper = Looper.myLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else if ((looper = Looper.getMainLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else { mEventHandler = null; } return native_setup(new WeakReference(this), cameraId, halVersion, ActivityThread.currentOpPackageName()); }
private native final int native_setup(Object camera_this, int cameraId, int halVersion, String packageName);
6.0以下的手机是通过手机管家之类的app来进行拦截的,通过拦截native层调用的方法进行拦截(猜测)
所以解决方法就是在进入正常逻辑的时候进行try-catch来避免程序崩溃
try { camera = Camera.open(0); }catch (Exception e){ //这里写权限被拒绝之后的处理showDialog("您想要使用此功能,需要使用相机权限、存储权限,请开启", "去开启", "取消"); }
6.0以上包括6.0,当拒绝权限申请时发生崩溃的处理方法
//大于23但是系统返回的授权标识是错误的,这里返回的null,在异常的时候给出提示 camera=Camera.open(0); try { Camera.Parameters param = camera.getParameters(); if (param!=null){ releaseCamera();//正常授权的话,需要在这里进行资源释放 PublicUtils.startFaceDetectActivity(PaymentChangeSingleActivity.this, FACECODE); }else { rationalePermissionDialog("您想要使用此功能,需要使用相机权限、存储权限,请开启", "去开启", "取消"); } }catch (Exception e){ Logger.i("Exception","Exception"+e); rationalePermissionDialog("您想要使用此功能,需要使用相机权限、存储权限,请开启", "去开启", "取消"); }
为什么要这样写呢?
camera=Camera.open(0); //这个获取到的的确是null。但是不会异常。当真正授权成功时这个没什么影响
但是如果拒绝仍旧返回的是已授权成功的话,
在
Camera.Parameters param = camera.getParameters();
就可以拦截这种假的授权结果,那么就不会进入下一个页面。也就不会有异常了
使用场景。我在项目中使用的RX
具体代码如下
@NeedsPermission({Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE}) public void toFaceVerify(BottomDialog dialog) { confirmPermiss(); }
private void confirmPermiss() { rxPermissions.request(Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE) .subscribe(new Consumer() { @Override public void accept(Boolean aBoolean) throws Exception { releaseCamera(); if (aBoolean) { if (Build.VERSION.SDK_INT>=23){ //大于23但是系统返回的授权标识是错误的,这里返回的null,在异常的时候给出提示 camera=Camera.open(0); try { Camera.Parameters param = camera.getParameters(); if (param!=null){ releaseCamera();//正常授权的话,需要在这里进行资源释放 PublicUtils.startFaceDetectActivity(PaymentChangeSingleActivity.this, FACECODE); }else { rationalePermissionDialog("您想要使用此功能,需要使用相机权限、存储权限,请开启", "去开启", "取消"); } }catch (Exception e){ Logger.i("Exception","Exception"+e); rationalePermissionDialog("您想要使用此功能,需要使用相机权限、存储权限,请开启", "去开启", "取消"); } }else { //属于在23之下,native层禁止方法调用。拒绝的时候产生异常,然后提示 try { camera = Camera.open(0); }catch (Exception e){ rationalePermissionDialog("您想要使用此功能,需要使用相机权限、存储权限,请开启", "去开启", "取消"); } } } else { rationalePermissionDialog("您想要使用此功能,需要使用相机权限、存储权限,请开启", "去开启", "取消"); } } }, new Consumer () { @Override public void accept(Throwable throwable) throws Exception { rationalePermissionDialog("我是来搞笑的", "去开启", "取消"); } }); }