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.創(chuàng)建PermissionManager對象府瞄,如果是在fragment中使用傳入參數是傳入 mFragment.getActivity()
mPermissionManager = new PermissionManager(this);//創(chuàng)建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);//所有的請求都被批準
}
}
在執(zhí)行完 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 最后回調所有 "允許" 的權限