天天看点

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);
    }