1. 程式人生 > >android6.0以上授權申請拒絕引起的崩潰(魅族mx6,魅藍note6)和Android6.0以下oppo系列手機拒絕許可權引起的崩潰問題的終極解決方案

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

具體程式碼如下

@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("我是來搞笑的", "去開啟", "取消");
}
            });
}

就這些了。希望可以解決大家的問題