android6.0以上授權申請拒絕引起的崩潰(魅族mx6,魅藍note6)和Android6.0以下oppo系列手機拒絕許可權引起的崩潰問題的終極解決方案
阿新 • • 發佈:2019-01-11
以下用相機許可權舉例
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 newCamera(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("我是來搞笑的", "去開啟", "取消"); } }); }
就這些了。希望可以解決大家的問題