首頁>技術>

前言

我們都知道從 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調下就可以了,

11
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 效能最佳化技巧:有序歸併