前言
我們都知道從 Android 6.0(level 23)開始,應用許可權都需要在執行時向用戶申請授予許可權,而不是像6.0以前只要在AndroidManifest.xml宣告就會預設授予對應的許可權。對於使用者來說這樣提高了隱私安全,但對於開發者來說,官方動態申請許可權api比較繁雜(至少我自己感覺是這樣的),而且幾乎在每個需要用到許可權的Activity都需要寫一遍,費時不說,我們來探討下如何才能更方便的實現吧。
我們先來看看官方獲取動態許可權的實現方式這裡以調起攝像頭拍照舉例說明
先在AndroidManifest.xml申明下拍照許可權<uses-permission android:name="android.permission.CAMERA" />
在需要使用到的Activity中實現下onRequestPermissionsResult方法,用於接收許可權申請結果的回撥
public class SampleActivity extends AppCompatActivity { private final int CAMERA_REQUEST = 8888; @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (grantResults != null && grantResults.length > 0) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { /*授予了許可權,可調起攝像頭拍照*/ Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, CAMERA_REQUEST); } else { /*無許可權*/ if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permissions[0])) { /*false 選擇了 Don’t ask again*/ /*拒絕許可權且選擇了不再詢問,直接跳去設定頁或彈窗提示*/ } else { /*拒絕許可權但沒選擇不再詢問*/ Toast.makeText(this, "您已拒絕拍照許可權", Toast.LENGTH_LONG).show(); } } } }}
呼叫系統api申請拍照許可權ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},CAMERA_REQUEST);
使用起來還算簡單,但是如果我們很多個頁面都需要動態申請許可權,那麼每個對應的Activity都需要覆寫onRequestPermissionsResult方法,這樣重複性的工作實在是太費時間了,所以,有沒有方法可以方便得動態獲取許可權呢?當然有,這也是這篇文章要分享給大家的一種做法。
動態許可權的推薦實現方式實現方式多種多樣,在這裡我們採用Fragment輔助我們實現,利用Fragment擁有與Activity一樣的生命週期和方法的特性,我們將onRequestPermissionsResult放在Fragment實現,具體實現細節如下:
單個許可權申請FragmentHelper.init(context).requestPermission(Manifest.permission.CAMERA, new FunctionFragment.OnSinglePermissionListener() { @Override public void onAccepted(FunctionFragment.Permission permission) { if (permission.granted) { /*允許拍照許可權*/ } else { if (!permission.shouldShowRequestPermissionRationale) { /*false 選擇了 Don’t ask again*/ /*拒絕許可權且選擇了不再詢問*/ } else { /*拒絕許可權但沒選擇不再詢問*/ Toast.makeText(this, "您已拒絕拍照許可權", Toast.LENGTH_LONG).show(); } } } });
多個許可權申請FragmentHelper.init(this).requestPermissions(new String[]{ Manifest.permission.CAMERA, Manifest.permission.ACCESS_COARSE_LOCATION }, new FunctionFragment.OnMultiPermissionListener() { @Override public void onAccepted(FunctionFragment.Permission[] permissions) { if (permissions != null && permissions.length > 0) { /*允許和拒絕的邏輯跟單個許可權申請一樣,見上*/ } } });
相關類
FunctionFragment
/** * 作者:lpx on 2020/4/14 17:24 * Email : [email protected] * Describe:功能Fragment(處理onActivityResult和onRequestPermissionsResult,如拍照和申請許可權) */public class FunctionFragment extends Fragment { private FragmentActivity mActivity; private Random mRandom = new Random(); private SparseArray<OnBasePermissionListener> mPermissionCallbacks = new SparseArray<>(); public FunctionFragment() { } public static FunctionFragment newInstance() { return new FunctionFragment(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /*設定為true,表示configuration change的時候,fragment例項不會被重新建立*/ setRetainInstance(true); mActivity = getActivity(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); handlePermissionCallBack(requestCode, permissions, grantResults); } /** * 申請許可權(單個) * * @param needPermissionCheck 是否需要許可權檢查(申請許可權前檢查是否有許可權,有則直接回調) */ public void requestPermission(String permission, boolean needPermissionCheck, OnSinglePermissionListener listener) { int requestCode = getSoleRequestCode(TYPE.PERMISSIONS_RESULT); mPermissionCallbacks.put(requestCode, listener); /*先判斷是否有許可權,有直接回調(使用者選擇了僅使用期間允許時調requestPermissions會拉起系統授權彈窗,實際上已經有許可權了)*/ String[] permissions = new String[]{permission}; if (needPermissionCheck && FragmentHelper.checkPermission(getContext(), permission)) { handlePermissionCallBack(requestCode, permissions, new int[]{PackageManager.PERMISSION_GRANTED}); } else { requestPermissions(permissions, requestCode); } } /** * 申請許可權(多個) * * @param needPermissionCheck 是否需要許可權檢查(申請許可權前檢查是否有許可權,有則直接回調) */ public void requestPermissions(String[] permissions, boolean needPermissionCheck, OnMultiPermissionListener listener) { int requestCode = getSoleRequestCode(TYPE.PERMISSIONS_RESULT); mPermissionCallbacks.put(requestCode, listener); if (needPermissionCheck) { /*先判斷是否有許可權,有直接回調(使用者選擇了僅使用期間允許時調requestPermissions會拉起系統授權彈窗,實際上已經有許可權了)*/ boolean isAllAllow = true; for (int i = 0, size = permissions.length; i < size; i++) { if (!FragmentHelper.checkPermission(getContext(), permissions[i])) { isAllAllow = false; break; } } if (isAllAllow) { int[] grantResults = new int[permissions.length]; for (int i = 0, size = grantResults.length; i < size; i++) { grantResults[i] = PackageManager.PERMISSION_GRANTED; } handlePermissionCallBack(requestCode, permissions, grantResults); } else { requestPermissions(permissions, requestCode); } } else { requestPermissions(permissions, requestCode); } } /** * 處理許可權申請結果 */ private void handlePermissionCallBack(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { OnBasePermissionListener callback = mPermissionCallbacks.get(requestCode); if (callback == null) { return; } int length = grantResults.length; if (length == 0) { return; } mPermissionCallbacks.remove(requestCode); if (callback instanceof OnSinglePermissionListener) { int grantResult = grantResults[0]; Permission permission; String name = permissions[0]; if (grantResult == PackageManager.PERMISSION_GRANTED) { permission = new Permission(name, true); } else { if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, name)) { permission = new Permission(name, false, true); } else { permission = new Permission(name, false, false); } } ((OnSinglePermissionListener) callback).onAccepted(permission); } else if (callback instanceof OnMultiPermissionListener) { Permission[] array = new Permission[length]; for (int i = 0; i < length; i++) { int grantResult = grantResults[i]; Permission permission; String name = permissions[i]; if (grantResult == PackageManager.PERMISSION_GRANTED) { permission = new Permission(name, true); array[i] = permission; } else { if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, name)) { permission = new Permission(name, false, true); } else { permission = new Permission(name, false, false); } } array[i] = permission; } ((OnMultiPermissionListener) callback).onAccepted(array); } } /** * 獲取唯一的requestCode,最多嘗試10次 */ private int getSoleRequestCode(TYPE type) { int requestCode; int tryCount = 0; do { requestCode = mRandom.nextInt(0x0000FFFF); tryCount++; } while ((type == TYPE.ACTYVITY_RESILT ? mPhotoCallbacks.indexOfKey(requestCode) >= 0 : mPermissionCallbacks.indexOfKey(requestCode) >= 0) && tryCount < 10); return requestCode; } /** * 許可權申請回調基礎監聽 */ public interface OnBasePermissionListener { } /** * 單個許可權申請回調監聽 */ public interface OnSinglePermissionListener extends OnBasePermissionListener { void onAccepted(Permission permission); } /** * 多個許可權申請回調監聽 */ public interface OnMultiPermissionListener extends OnBasePermissionListener { void onAccepted(Permission[] permission); } public enum TYPE { /** * 處理onActivityResult */ ACTYVITY_RESILT, /** * 處理onRequestPermissionsResult */ PERMISSIONS_RESULT } public static class Permission { /** * 許可權名 */ public String name; /** * 是否允許授權 */ public boolean granted; /** * false 選擇了 Don’t ask again */ public boolean shouldShowRequestPermissionRationale; public Permission(String name, boolean granted) { this(name, granted, false); } public Permission(String name, boolean granted, boolean shouldShowRequestPermissionRationale) { this.name = name; this.granted = granted; this.shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale; } }}
FragmentHelper
/** * 作者:lpx on 2020/4/14 14:39 * Email : [email protected] * Describe:輔助調起FunctionFragment */public class FragmentHelper { private static final String TAG_PERMISSION = "TAG_FUNCTION_FRAGMENT"; private FragmentActivity mActivity; private FragmentHelper(FragmentActivity mActivity) { this.mActivity = mActivity; } private FragmentHelper() { } /** * 返回FunctionFragment例項並與activity繫結 */ private FunctionFragment getFunctionFragment(FragmentActivity activity) { FunctionFragment fragment = (FunctionFragment) mActivity.getSupportFragmentManager().findFragmentByTag(TAG_PERMISSION); if (fragment == null) { fragment = FunctionFragment.newInstance(); FragmentManager fragmentManager = activity.getSupportFragmentManager(); fragmentManager .beginTransaction() .add(fragment, TAG_PERMISSION) .commitAllowingStateLoss(); fragmentManager.executePendingTransactions(); } return fragment; } /** * 返回FunctionFragment例項並與activity繫結 */ private FunctionFragment getFunctionFragment(FragmentManager fragmentManager) { FunctionFragment fragment = (FunctionFragment) fragmentManager.findFragmentByTag(TAG_PERMISSION); if (fragment == null) { fragment = FunctionFragment.newInstance(); fragmentManager .beginTransaction() .add(fragment, TAG_PERMISSION) .commitAllowingStateLoss(); fragmentManager.executePendingTransactions(); } return fragment; } /** * 申請許可權(多個) * * @param needPermissionCheck 是否需要許可權檢查(申請許可權前檢查是否有許可權,有則直接回調) */ public void requestPermissions(String[] permissions, boolean needPermissionCheck, FunctionFragment.OnMultiPermissionListener listener) { getFunctionFragment(mActivity).requestPermissions(permissions, needPermissionCheck, listener); } /** * 申請許可權(單個) * * @param needPermissionCheck 是否需要許可權檢查(申請許可權前檢查是否有許可權,有則直接回調) */ public void requestPermission(String permission, boolean needPermissionCheck, FunctionFragment.OnSinglePermissionListener listener) { getFunctionFragment(mActivity).requestPermission(permission, needPermissionCheck, listener); } /** * 申請許可權(多個) * * @param needPermissionCheck 是否需要許可權檢查(申請許可權前檢查是否有許可權,有則直接回調) */ public void requestPermissions(FragmentManager fragmentManager, String[] permissions, boolean needPermissionCheck, FunctionFragment.OnMultiPermissionListener listener) { getFunctionFragment(fragmentManager).requestPermissions(permissions, needPermissionCheck, listener); } /** * 申請許可權(單個) * * @param needPermissionCheck 是否需要許可權檢查(申請許可權前檢查是否有許可權,有則直接回調) */ public void requestPermission(FragmentManager fragmentManager, String permission, boolean needPermissionCheck, FunctionFragment.OnSinglePermissionListener listener) { getFunctionFragment(fragmentManager).requestPermission(permission, needPermissionCheck, listener); } /** * 申請許可權(多個) */ public void requestPermissions(String[] permissions, FunctionFragment.OnMultiPermissionListener listener) { getFunctionFragment(mActivity).requestPermissions(permissions, false, listener); } /** * 申請許可權(單個) */ public void requestPermission(String permission, FunctionFragment.OnSinglePermissionListener listener) { getFunctionFragment(mActivity).requestPermission(permission, false, listener); } /** * 申請許可權(多個) */ public void requestPermissions(FragmentManager fragmentManager, String[] permissions, FunctionFragment.OnMultiPermissionListener listener) { getFunctionFragment(fragmentManager).requestPermissions(permissions, false, listener); } /** * 申請許可權(單個) */ public void requestPermission(FragmentManager fragmentManager, String permission, FunctionFragment.OnSinglePermissionListener listener) { getFunctionFragment(fragmentManager).requestPermission(permission, false, listener); } /** * 初始化返回Activity對應繫結的FunctionFragment例項 */ public static FragmentHelper init(FragmentActivity fragmentActivity) { return new FragmentHelper(fragmentActivity); } /** * 初始化返回Activity對應繫結的FunctionFragment例項 */ public static FragmentHelper init() { return new FragmentHelper(); } /** * 檢查許可權 */ public static boolean checkPermission(Context context, @NonNull String permission) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } else { return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; } }}
怎麼樣,是不是這樣就方便很多了,只要在需要動態申請許可權的地方透過FragmentHelper調下就可以了,
最新評論