這可能是最精簡的Android6.0執行時許可權處理,70行程式碼的工具類。附:各種許可權詳細處理
0x00:前言
對於Android6.0執行時許可權的處理方式網上有很多,包括註解,RxJava等等。一直沒有正面提到我關心的問題--如果我不在Activity或者Fragment裡面,需要執行時許可權該怎麼去做?導致我開始一直以為執行時許可權的處理必需要在Activity或者Fragment之中。
那麼:
我有一個錄音的自定義控制元件在很多頁面需要使用怎麼辦?
我有一個聯絡人列表,要在adapter裡面撥打電話怎麼辦?
我有一個定位的工具類要在多個頁面使用怎麼辦?
等等...
之前我還問過一些同行,他說用回撥,回撥到Activity或者Fragment,我當時覺得是一種解決方案,但是卻很麻煩,如果有多個頁面使用,那不是要處理很多次。
直到某一天在github上看到一個分享了簡單的工具類MPermissionUtils
,一下子解決了我的疑惑,雖然他也沒有明確給出答案,但是我從他的使用上卻恍然大悟,原來是一開始我就理解錯了。我們只需要把系統回撥方法onRequestPermissionsResult
放到BaseActivity裡面,將處理結果通過工具類調出來,加一個自定義的回撥到請求的發起處即可。
因為你要用到執行時許可權的地方總要依賴於Activity的存在,如果不再Activity裡面或者當前程式碼獲取不到Activity,那就傳過去,一切的處理結果都會回到你發起請求所在的Activity。
那麼一不做二不休,我們這時候有沒有考慮Fragment裡面的處理其實是多餘的,我們可不可以都放到Activity裡面來處理。於是就化繁為簡產生了我的
0x01:程式碼實現
public class XPermissionUtils {
private static int mRequestCode = -1;
private static OnPermissionListener mOnPermissionListener;
public interface OnPermissionListener {
void onPermissionGranted();
void onPermissionDenied();
}
@TargetApi(Build.VERSION_CODES.M)
public static void requestPermissions(Context context, int requestCode
, String[] permissions, OnPermissionListener listener) {
if (context instanceof Activity) {
mOnPermissionListener = listener;
List<String> deniedPermissions = getDeniedPermissions(context, permissions);
if (deniedPermissions.size() > 0) {
mRequestCode = requestCode;
((Activity) context).requestPermissions(deniedPermissions
.toArray(new String[deniedPermissions.size()]), requestCode);
} else {
if (mOnPermissionListener != null)
mOnPermissionListener.onPermissionGranted();
}
} else {
throw new RuntimeException("Context must be an Activity");
}
}
/**
* 獲取請求許可權中需要授權的許可權
*/
private static List<String> getDeniedPermissions(Context context, String... permissions) {
List<String> deniedPermissions = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED) {
deniedPermissions.add(permission);
}
}
return deniedPermissions;
}
/**
* 請求許可權結果,對應Activity中onRequestPermissionsResult()方法。
*/
public static void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (mRequestCode != -1 && requestCode == mRequestCode) {
if (mOnPermissionListener != null) {
if (verifyPermissions(grantResults)) {
mOnPermissionListener.onPermissionGranted();
} else {
mOnPermissionListener.onPermissionDenied();
}
}
}
}
/**
* 驗證所有許可權是否都已經授權
*/
private static boolean verifyPermissions(int[] grantResults) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
}
0x02:使用方式
以撥打電話為例
1、首先AndroidManifest
中配置必要的許可權
<uses-permission android:name="android.permission.CALL_PHONE"/>
2、在基類中加上回調方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
grantResults) {
XPermissionUtils.onRequestPermissionsResult(requestCode, permissions, grantResults);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
3、呼叫工具類方法
XPermissionUtils.requestPermissions(Context context, int requestCode, String[] permissions, OnPermissionListener listener)
這裡主要注意這個Context必需是一個Activity
如果在Activity中可以傳this
;
如果在Fragment中傳getActivity()
;
如果在View中傳getContext()
;
等等.....
private void doCallPhone() {
XPermissionUtils.requestPermissions(this, 1, new String[]{Manifest.permission
.CALL_PHONE}, new XPermissionUtils.OnPermissionListener() {
@Override
public void onPermissionGranted() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10010"));
startActivity(intent);
}
@Override
public void onPermissionDenied() {
//彈出許可權被禁用的提示框
}
});
}
0x03:各種執行時許可權處理詳談
其實在6.0之前已經存在執行時許可權,只不過沒有明確提出這個概念,在6.0之前,獲取位置、讀取通訊錄、拍照、錄音等都是需要在操作的時候去獲取許可權的。那麼這些許可權的區別是6.0以後需要我們去寫請求獲取許可權的程式碼,而之前是當代碼執行到需要許可權的地方就會彈出提示框。
那麼針對不同的許可權可能有不同的處理方式,下面簡單列舉,如果需要看程式碼可以在原始碼的Demo中檢視
1、撥打電話
撥打電話其實如果不是產品要求直接撥出去可以使用調轉到撥號頁面實現的,這個不需要許可權:
Intent intent = new Intent(Intent.ACTION_DIAL);
Uri data = Uri.parse("tel:10010");
intent.setData(data);
startActivity(intent);
2、錄音
(1)錄音許可權在6.0之前是無法判斷是否獲取許可權的,只能通過非常規的方法獲取,詳見專案Demo
(2)長按按鈕錄音,在第一次獲取許可權的時候需要特殊處理,彈出獲取許可權的提示框之後手指已經離開,不能進行錄音的操作。
3、開啟相機
相機許可權在6.0之前同樣也是無法判斷是否獲取許可權的,只能通過非常規的方法獲取,詳見專案Demo
4、獲取位置
(1)首先手機需要開啟位置服務,如果沒有開啟,那麼即使app開啟獲取位置許可權也是獲取不到的
(2)(使用系統Api,有時候小功能不需要整合百度,高德)要注意在室內如果選擇Gps定位會獲取不到位置,這裡可以參考Demo中LocationUtils
的實現思路。
5、獲取外部儲存
這個在有些手機上比較特殊,比如小米就不需要執行時許可權,華為就需要,這個還是需要在使用的時候主動請求一下。
0x04 特別鳴謝
文/AndSync(簡書作者)
原文連結:http://www.jianshu.com/p/4a60b064a0ab
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。