前言
眾所周知,谷歌在Android 6.0提出了危險權(quán)限這個概念,讓我們開發(fā)應(yīng)用的時候,需要花一些時間去關(guān)注動態(tài)權(quán)限的處理.今天我就把在動態(tài)權(quán)限這塊地方遇到的坑給大家說說.
我們都知道,在安卓開發(fā)中,經(jīng)常需要用到幾個比較常見的權(quán)限,例如:
Manifest.permission.READ_EXTERNAL_STORAGE, //儲存空間權(quán)限
Manifest.permission.READ_PHONE_STATE, //手機狀態(tài)權(quán)限
Manifest.permission.ACCESS_FINE_LOCATION,//位置訪問權(quán)限
Manifest.permission.CAMERA //相機權(quán)限
```
我們在做動態(tài)權(quán)限適配的時候一般都需要多個權(quán)限同時進行處理,
,剛剛開始接觸動態(tài)權(quán)限的時候,感覺一個權(quán)限還比較好處理,邏輯是:
第一,先判斷是否獲得權(quán)限
第二,如果沒有,就去申請權(quán)限,處理回調(diào)方法然后執(zhí)行想要的邏輯
但是多個權(quán)限,就沒有我們想象的那么簡單了,你需要關(guān)注到每個權(quán)限是否都已經(jīng)有申請過,由于公司的APP的設(shè)計是在Splash界面需要同時獲得多個權(quán)限,我必須要保證每個權(quán)限都要被獲取,因此我剛剛開始的想法是這樣的:
第一步, 判斷權(quán)限. 遍歷所有權(quán)限進行判斷權(quán)限是否都被獲取,得到一個是否全部獲得權(quán)限的標記,通過標記判斷是否需要進行權(quán)限申請。
第二步, 申請權(quán)限. 如果當中有沒有獲取權(quán)限的,那就需要申請權(quán)限, 在權(quán)限申請回調(diào)拿到結(jié)果, 判斷沒有被申請通過的權(quán)限, 存放在一個集合中, 然后再去進行單個權(quán)限申請,依然對返回值進行判斷,如果不通過就成重新把未通過的權(quán)限進行申請,通過就進入程序.
這種類似于循環(huán)式的做法,看起來可行,實則漏洞百出,我似乎忽略了一種情況,那就是當用戶拒絕權(quán)限并禁止訪問的時候,APP會進入假死狀態(tài),一直會卡在Splash界面,后來我也在網(wǎng)上找了一些資料,發(fā)現(xiàn)shouldShowRequestPermissionRationale(String permisssion) 這個方法可以幫我解決問題,于是我邏輯是這樣寫的!
boolean flag=false;
for (String permission : permissions) {
if (!shouldShowRequestPermissionRationale(permission)) {
flag = true;
break;
}
}
if(flag){
//為true 就進入權(quán)限設(shè)置
}else{
//為false 表示沒有被禁止詢問 直接進行上述我寫的邏輯(判斷、申請權(quán)限等)
}
于是,我卸載重新安裝應(yīng)用,部署在模擬器上,一運行,出BUG了
我發(fā)現(xiàn),如果我是重新安裝應(yīng)用,程序直接引導(dǎo)我去設(shè)置界面設(shè)置權(quán)限,連申請權(quán)限都不走了!我心里一萬只草泥馬奔騰而過,這是什么鬼?難道這個shouldShowRequestPermissionRationale()的不是關(guān)心不再詢問[checkbox]的結(jié)果么?
于是我再新建一個應(yīng)用進行測試,這次我轉(zhuǎn)換了一下我的思路,我先用單個權(quán)限進行測試,步驟如下:
if (checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED) { //先對權(quán)限進行判斷
if (shouldShowRequestPermissionRationale(permission)) {
LogUtils.d("方法返回值為true時"); //系統(tǒng)或人為關(guān)閉時,可以跳轉(zhuǎn)到設(shè)置頁面進行設(shè)置
new AlertDialog.Builder(this)
.setMessage("為了保證應(yīng)用能夠正常使用,請前往設(shè)置如下權(quán)限:" +
"位置訪問權(quán)限、相機權(quán)限、儲存空間權(quán)限")
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
}
}).show();
} else {
LogUtils.d("方法返回值為false時");
requestPermissions(new String[]{permission}, REQUEST_SINGLE_PERMISSION);
}
} else {
//權(quán)限已經(jīng)被申請
LogUtils.d("權(quán)限被接受");
}
原來還是因為這個方法[shouldShowRequestPermissionRationale(xxx)]導(dǎo)致的,當為true的時候,是表示有人為選中拒絕(被禁止詢問),或者是系統(tǒng)默認拒絕狀態(tài)(一些廠商會將底層權(quán)限設(shè)置進行修改,比如小米等),而為false時 只是表示權(quán)限沒有被通過的意思.我去 ,原來網(wǎng)上的文章也有時候會搞錯,真心尷尬。
最后,如果大家在開發(fā)中,遇到動態(tài)權(quán)限處理,最好還是用別人的框架吧,除非你時間充裕,并且想學(xué)習下動態(tài)權(quán)限其中的原理,否則 ,勸大家還是用框架,畢竟框架用起來方便,而且考慮比較全面.