android6.0以上授权申请拒绝引起的崩溃(魅族mx6,魅蓝note6)和Android6.0以下oppo系列手机拒绝权限引起的崩溃问题的终极解决方案


以下用相机权限举例

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<Camera>(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

PermissionsDispatcher 和  RXPermissions

具体代码如下

@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<Boolean>() {
                @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<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    rationalePermissionDialog("我是来搞笑的", "去开启", "取消");

                }
            });
}

就这些了。希望可以解决大家的问题

猜你喜欢

转载自blog.csdn.net/u013934399/article/details/79570597