Permission組件解析

Android 6.0之后,對于一些敏感的權限,需要我們手動請求,本文介紹一個權限組件Permisssion,主要是用于Android6.0以后(也就是API>23)的敏感權限請求,如果項目中的targetSdkVersion大于等于23,并且某個activity要需要一個或者多個危險權限的話可以用此組件進行判斷是否擁有權限以及請求權限。

組件的使用

1.在module的build.gradle 中增加: compile 'com.neteaseyx.permission:permission-lib:1.0.0',
2.創建PermissionManager對象,如果是在fragment中使用傳入參數是傳入 mFragment.getActivity()

 mPermissionManager = new PermissionManager(this);//創建PermissionManager對象

3.明確所需權限,可以是多個權限(哪些是危險權限都可以查得到),這些權限都是用Manifest.permission.xxx聲明

 final String[] permissions = {
            Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.ACCESS_FINE_LOCATION
    };

4.在需要請求權限的地方使用PermissionManager.requestPermissions 方法請求權限,第一個參數是請求碼,第二個參數是要請求的權限,第三個參數是請求結果的回調,PermissionCallback里面有四個回調方法,onGranted_Third是回調所有允許的權限,onExplanation是回調拒絕但是沒有勾選不再詢問的權限,onNormalDenied_Second是回調所有拒絕的權限,onNoMoreAskDenied_First是回調所有已經拒絕,而且勾選了不再詢問的權限

mPermissionManager.requestPermissions(PERMISSION_REQ_CODE, permissions, new PermissionCallback() {

                @Override
                public void onGranted_Third(String... permissions) {    //回調所有允許的權限
                    for (String permission : permissions) {
                        addTextToResult(permission + "\n  -已批準\n", permission);
                    }
                }

                @Override
                public void onExplanation(String... permissions) {  //拒絕但沒有勾選不再詢問,會通過這個方法回調
                    mPermissionManager.showRequestDialog(MainActivity.this, permissions, PERMISSION_REQ_CODE);
                }

                @Override
                public void onNormalDenied_Second(String... permissions) { //回調所有拒絕的權限
                    for (String permission : permissions) {
                        addTextToResult(permission + "\n  -已拒絕\n", permission);
                    }
                }

                @Override
                public void onNoMoreAskDenied_First(String... permissions) { //拒絕,而且勾選了不再詢問
                    for (String permission : permissions) {
                        addTextToResult(permission + "\n  -已永久拒絕\n", permission);
                    }
                }
            });

5.在 Activity 或者 Fragment 的 onRequestPermissionsResult 方法中調用 PermissionManager.onRequestPermissionResult, 否則不會有任何結果回調

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    mPermissionManager.onRequestPermissionResult(requestCode, permissions, grantResults);
}

組件內部實現

讓我們看看組件內部是怎么實現的,首先是PermissionManager.requestPermissions 方法請求權限,它先判斷是否所有的請求都被批準了,如果都被批準了,直接回調onGranted_Third(permissions),回調所有允許的權限,如果不是,就遍歷權限集合,判斷是否要用戶選擇,將需要用戶選擇的權限添加到permissionsToExplainList集合里,并轉換成數組,如果數組不為空那么就彈出相應請求框

注意:這里callback.onExplanation(permissionsToExplain);一般情況是用戶上一次選擇了拒絕(沒有勾選不再詢問),這次又重新請求,通常在此處還需要再次彈出請求對話框,而且這里不會自動出現權限請求彈窗, 需要在用戶處理完之前提到的 "解釋" 之后, 手動通過 PermissionManager.showRequestDialog 顯示彈窗

 /**
 * 請求權限
 *
 * @param requestCode 本次請求的唯一標識(不要過大,最好小于999)
 * @param permissions 本次需要請求的權限,可以多個
 * @param callback    本次請求在用戶選擇完畢后的回調
 */
public void requestPermissions(int requestCode, String[] permissions, PermissionCallback callback) {
    mCallbackMap.put(requestCode, callback);
    if (!isPermissionsGranted(permissions)) {//是否所有的請求都被批準了,如果沒有被批準
        List<String> permissionsToExplainList = new ArrayList<>(3);
        for (String permission : permissions) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permission)) {//判斷是否應該請求,里面做了是否是危險權限的判斷
                permissionsToExplainList.add(permission);  //把應該請求的權限添加到permissionsToExplainList集合
            }
        }
        String[] permissionsToExplain = permissionsToExplainList.toArray(new String[permissionsToExplainList.size()]);//集合轉化為數組
        if (permissionsToExplain.length != 0) {
            callback.onExplanation(permissionsToExplain);
        } else {
            showRequestDialog(mActivity, permissions, requestCode);
        }
    } else {
        callback.onGranted_Third(permissions);//所有的請求都被批準
    }
}

在執行完 PermissionManager.requestPermissions 后, 如果有權限請求需要用戶選擇, 系統會彈出相應請求框
如果沒有權限需要用戶選擇(所有權限或是已經允許, 或是已經拒絕, 或是永久拒絕), 直接回調相應結果
接下來我們來看看回調結果

* @param requestCode  請求的唯一標識
 * @param permissions  請求的權限
 * @param grantResults 請求的結果
 */
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
    PermissionCallback callback = mCallbackMap.get(requestCode);
    if (callback != null) {
        List<String> grantedList = new ArrayList<>(3);//用戶同意的權限
        List<String> normalDeniedList = new ArrayList<>(3);//用戶拒絕的權限,但是沒有勾選不再詢問
        List<String> noMoreAskDeniedList = new ArrayList<>(3);//用戶拒絕的權限,而且勾選了不再詢問
        for (int i = 0; i < permissions.length; i++) {
            if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                grantedList.add(permissions[i]);
            } else {
                if (!ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permissions[i])) {
                    noMoreAskDeniedList.add(permissions[i]);
                } else {
                    normalDeniedList.add(permissions[i]);
                }
            }
        }
        callback.onNoMoreAskDenied_First(noMoreAskDeniedList.toArray(new String[noMoreAskDeniedList.size()]));
        callback.onNormalDenied_Second(normalDeniedList.toArray(new String[normalDeniedList.size()]));
        callback.onGranted_Third(grantedList.toArray(new String[grantedList.size()]));
    }
}

首先定義了三個數組,以個是表示用戶同意的權限,一個是用戶拒絕的權限,但是沒有勾選不再詢問,一個是用戶拒絕的權限而且勾選了不再詢問,然后開始遍歷權限數組,將用戶選擇之后的權限分成三份,放在對應的結合里,然后調用回調,傳到相應的activity中,在activity中的callback里就可以知道哪些權限是用戶拒絕或者同意了的,還可以對相應的權限進行操作。

注意:PermissionCallback里的各種結果的回調有個先后順序:

  • onExplanation 如果有權限 "上一次選擇了拒絕, 但沒有勾選不再詢問", 最開始會通過此方法回調
  • onNoMoreAskDenied_First 然后回調所有 "不再詢問 且 勾選拒絕" 的權限
  • onNormalDenied_Second 然后回調所有 "拒絕" 的權限
  • onGranted_Third 最后回調所有 "允許" 的權限
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容