天天看點

RxPermision安卓運作時授權

       項目中因為SDK依賴庫的關系,需要将安卓SDK更新到API 23以上。更新以後就需要适配運作時授權。Google将權限分為兩類,一類是Normal Permissions,這類權限一般不涉及使用者隐私,是不需要使用者進行授權的,比如手機震動、通路網絡等;另一類是Dangerous Permission,一般是涉及到使用者隐私的,需要使用者進行授權,比如讀取sdcard、通路通訊錄等。對于23以上的版本,Dangerous Permission應用安裝以後需要運作時授權,顯式授予app相關權限。

1、運作時授權原理

标準的授權過程:

RxPermision安卓運作時授權

但這裡有個問題,那就是在系統授權彈窗環節,提醒框會有個不再提示的複選框,如果使用者點選不太提示,并拒絕授權,那麼再下次授權的時候,系統授權彈窗的提示框就不會在提示,是以我們很有必要需要自定義權限彈窗提示框,那麼流程圖就變成如下了。

RxPermision安卓運作時授權

對于這種情況,就需要程式處理,引導使用者進行授權處理。

2、授權處理的方式

方案一:進入首頁面優先處理授權,隻允許使用者授權成功才進行處理,防止權限不足引起一些異常。這種方式最大的優勢就是避免權限不足引起一些不可預見的異常CRASH,而且避免了使用者操作過程中經常出現授權的處理。

微信就是采取這種模式。

方案二:在頁面運作時根據需要授權。這種模式比較靈活,給使用者相對的選擇權。缺點是必須要規避所有的權限不足引起的異常,而且對于一些背景的操作,例如啟動後進行日志資訊采集需要讀取GPS、通訊錄等操作,如果使用者未授權的情況下,采集不到資訊。而且使用者不授予權限并且不在提示彈窗的情況下,基本上這些相關功能失效了。

項目中采用的“方案一+方案二”的方式。

3、授權處理

      Activity授權處理分為兩部分,通過requestPermission請求權限,通過onRequestPermissionsResult 處理授權結果。處理顯得比較分散和麻煩。當然可以在基類中統一內建授權處理。

4、RxPermission封裝了授權處理,使用很友善。實作原理:

RxPermission利用Fragment也能申請授權并且能夠接收授權結果的原理,将授權處理內建在一個Fragment中。

1)RxPermission封裝一個專門用于授權的Fragment類RxPermissionsFragment,用于處理申請授權和授權結果的處理;

2)将RxPermissionsFragment對象挂載到Activity上;

3)Activity調用RxPermission申請授權,通過回調接收授權結果。

RxPermision安卓運作時授權

5、RxPermission使用方法:

請求授權:通過RxPermission的requestEach申請多個權限。

public PermissionManager(Activity activity) {
        this.activity = activity;
        this.rxPermissions = new RxPermissions(activity);
        rxPermissions.setLogging(true);
    }

    public void setRequestPermissions(String[] permissions) {
        this.requestPermissions = permissions;
        this.permissionCount = null != permissions ? permissions.length : 0;
        this.grantedMap = new HashMap<>();
    }

    /**
     * 請求授權
     */
    public void requestPermission() {
        grantedMap.clear();
        rxPermissions.requestEach(requestPermissions)
                .subscribe(new Consumer<Permission>() {

                    /**
                     * 授權結果回調
                     *
                     * @param permission : 每一個請求的授權權限。
                     * @throws Exception
                     */
                    @Override
                    public void accept(Permission permission) throws Exception {
                        if(permission.granted) {
                            //全部授權成功
                            Log.d(TAG, "requestPermission success: " + permission);
                            grantedMap.put(permission.name, true);
                        } else if(permission.shouldShowRequestPermissionRationale) {
                            //顯示授權彈窗
                            Log.d(TAG, "requestPermission failed: " + permission);
                            grantedMap.put(permission.name, false);
                        } else {
                            grantedMap.put(permission.name, false);
                        }

                        //授權完成時進行檢測,如果仍然有權限未擷取彈窗提示
                        if(grantedMap.size() == permissionCount) {
                            boolean isAllGranted = true;
                            //檢查是否仍然存在未授權的情況
                            Iterator it = grantedMap.entrySet().iterator();
                            while (it.hasNext()) {
                                Map.Entry<String, Boolean> entry = (Map.Entry<String, Boolean>) it.next();
                                if(!entry.getValue().booleanValue()) {
                                    //仍然存在未授權成功的權限
                                    isAllGranted = false;
                                    break;
                                }
                            }
                            if(!isAllGranted) {
                                //仍然有權限未授權顯示授權彈窗
                                showPermissionDialog();
                            }
                        }
                    }
                });
    }
           
如果使用者不再顯示授權彈窗,引導使用者去授權      
/**
     * 打開設定頁面授權設定
     *
     */
    private void openSettingPermission() {
        // vivo 點選設定圖示>加速白名單>我的app
        //      點選軟體管理>軟體管理權限>軟體>我的app>信任該軟體
        Intent appIntent = activity.getPackageManager().getLaunchIntentForPackage("com.iqoo.secure");
        if(appIntent != null){
            activity.startActivityForResult(appIntent, REQUEST_CODE_SETTING);
            return;
        }

        // oppo 點選設定圖示>應用權限管理>按應用程式管理>我的app>我信任該應用
        //      點選權限隐私>自啟動管理>我的app
        appIntent = activity.getPackageManager().getLaunchIntentForPackage("com.oppo.safe");
        if(appIntent != null){
            activity.startActivityForResult(appIntent, REQUEST_CODE_SETTING);
            return;
        }

        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
            intent.setData(Uri.fromParts("package",
                    activity.getApplication().getPackageName(), null));
        } else {
            intent.setAction(Intent.ACTION_VIEW);
            intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
            intent.putExtra("com.android.settings.ApplicationPkgName",
                    activity.getApplication().getPackageName());
        }
        activity.startActivityForResult(intent, REQUEST_CODE_SETTING);
    }