RxPermissions原理解析

为什么需要申请动态权限

android在6.0之前申请权限是在manifest中配置的,但在6.0版本了保护用户隐私引入了一种新的权限模式,这种模式权限分为两种:

  • 非敏感权限:这种权限是不需要动态申请,只需要在manifest中配置,和6.0之前请求权限是一样的。

  • 敏感权限:在用户需要使用一些敏感权限需要向系统动态申请,这种权限是分组的,一组权限只要申请了其中的一个,同组的其他权限也就被申请了。

    特殊权限组(来自Google文档)

    Permission Group Permissions
    CALENDAR READ_CALENDAR``WRITE_CALENDAR
    CALL_LOG READ_CALL_LOG WRITE_CALL_LOG``PROCESS_OUTGOING_CALLS
    CAMERA CAMERA
    CONTACTS READ_CONTACTS``WRITE_CONTACTS``GET_ACCOUNTS
    LOCATION ACCESS_FINE_LOCATION``ACCESS_COARSE_LOCATION
    MICROPHONE RECORD_AUDIO
    PHONE READ_PHONE_STATE``READ_PHONE_NUMBERS``CALL_PHONE``ANSWER_PHONE_CALLS``ADD_VOICEMAIL``USE_SIP
    SENSORS BODY_SENSORS
    SMS SEND_SMS``RECEIVE_SMS``READ_SMS``RECEIVE_WAP_PUSH``RECEIVE_MMS
    STORAGE READ_EXTERNAL_STORAGE``WRITE_EXTERNAL_STORAGE

原生申请权限方式

  1. 检查系统是否有该权限,没有则调用requestPermissions方法

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
      ActivityCompat.requestPermissions(this, Manifest.permission.CAMERA,10)
    }
    
  2. 重写onRequestPermissionsResult,判断是否申请成功

    if (requestCode == 10) {
                if (TextUtils.equals(permissions[0],Manifest.permission.WRITE_EXTERNAL_STORAGE) && grantResults[0] == PackageManager.PERMISSION_DENIED) {
                    //用户不同意,向用户展示该权限作用
                    if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                        alertDialog( "请注意", "本应用需要使用访问本地存储权限,否则无法正常使用!", false, "确定", "取消", DialogInterface.OnClickListener { _, _ -> finish() }, DialogInterface.OnClickListener { _, _ -> finish() })
                        return
                    }
                }
            }
    

RxPermissions申请权限方式

  • 单个权限的申请

    RxPermissions(this).request(Manifest.permission.ACCESS_COARSE_LOCATION)
            .subscribe {
                if (it) {
                    //申请成功
                } else {
                    //申请被拒
                }
    
            }
    
  • 多个权限的申请

    RxPermissions(this).requestEach(
            Manifest.permission.READ_CONTACTS,
            Manifest.permission.WRITE_CONTACTS
        )
            .subscribe { permission ->
                when {
                    permission.granted -> {
                        //申请成功
                    }
                    permission.shouldShowRequestPermissionRationale -> {
                        // 用户拒绝了该权限,没有选择 不再提示 ,下次请求时,还会提示请求权限的对话框
                    }
                    else -> {
                        // 用户拒绝了该权限,选择了 不再提示 ,再次请求不会询问,需要在setting中开启
                    }
                }
            }
    

为什么RxPermissions权限请求相比系统的权限请求简洁了许多,其实框架内部帮我们实现了那些复杂的操作,接下来我们看一下RxPermissions内部是怎么实现的。

源码浅析

RxPermissions主要的是包含3个类,分别是PermissionRxPermissionsRxPermissionsFragment

RxPermissions原理解析_第1张图片

首先我们先看构造方法,该方法只有一行代码,获取Fragment

public RxPermissions(@NonNull Activity activity) {
        mRxPermissionsFragment = getRxPermissionsFragment(activity);
    }

getRxPermissionsFragment方法里,根据TAG找rxPermissionFragment,为空的话就创建一个rxPermissionFragment然后添加到Activity中,权限的请求及回调都在这个Fragment中完成,具体下面会讲。

private RxPermissionsFragment getRxPermissionsFragment(Activity activity) {
        RxPermissionsFragment rxPermissionsFragment = findRxPermissionsFragment(activity);
        boolean isNewInstance = rxPermissionsFragment == null;
        if (isNewInstance) {
            rxPermissionsFragment = new RxPermissionsFragment();
            FragmentManager fragmentManager = activity.getFragmentManager();
            fragmentManager
                    .beginTransaction()
                    .add(rxPermissionsFragment, TAG)
                    .commitAllowingStateLoss();
            fragmentManager.executePendingTransactions();
        }
        return rxPermissionsFragment;
    }
private RxPermissionsFragment findRxPermissionsFragment(Activity activity) {
  			//根据TAG找到fragment
        return (RxPermissionsFragment) activity.getFragmentManager().findFragmentByTag(TAG);
    }

接下来调用方法requestensurerequestImplementation

public Observable<Boolean> request(final String... permissions) {
        return Observable.just(TRIGGER).compose(ensure(permissions));
    }

public <T> ObservableTransformer<T, Boolean> ensure(final String... permissions) {
  			// 将Observable转换为Observable
        return new ObservableTransformer<T, Boolean>() {
            @Override
            public ObservableSource<Boolean> apply(Observable<T> o) {
                return request(o, permissions)
                        .buffer(permissions.length)
                        .flatMap(new Function<List<Permission>, ObservableSource<Boolean>>() {
                            @Override
                            public ObservableSource<Boolean> apply(List<Permission> permissions) throws Exception {
                              //如果permissions为空,直接返回Observable.empty(),不执行下面的逻辑
                                if (permissions.isEmpty()) {
                                    return Observable.empty();
                                }
                              //遍历permissions,如果有一个Permission被拒,则返回false并发送出去
                                for (Permission p : permissions) {
                                    if (!p.granted) {
                                        return Observable.just(false);
                                    }
                                }
                              //如果权限都申请成功,则发送true
                                return Observable.just(true);
                            }
                        });
            }
        };
    }

private Observable<Permission> requestImplementation(final String... permissions) {
        List<Observable<Permission>> list = new ArrayList<>(permissions.length);
        List<String> unrequestedPermissions = new ArrayList<>();

        //遍历permissions,在mRxPermissionsFragment中判断该权限是否已经请求成功,如果成功构建成Permission通过Observable.just()发送出去并将Observable添加到list中
        for (String permission : permissions) {
            mRxPermissionsFragment.log("Requesting permission " + permission);
            if (isGranted(permission)) {
                list.add(Observable.just(new Permission(permission, true, false)));
                continue;
            }
          // 如果权限被拒绝
            if (isRevoked(permission)) {
                list.add(Observable.just(new Permission(permission, false, false)));
                continue;
            }

          //如果权限还没有申请过,则创建一个PublishSubject并添加到 unrequestedPermissions中
            PublishSubject<Permission> subject = mRxPermissionsFragment.getSubjectByPermission(permission);
            if (subject == null) {
                unrequestedPermissions.add(permission);
                subject = PublishSubject.create();
                mRxPermissionsFragment.setSubjectForPermission(permission, subject);
            }

            list.add(subject);
        }

        if (!unrequestedPermissions.isEmpty()) {
            String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]);
          //调用requestPermissionsFromFragment中的方法申请权限
            requestPermissionsFromFragment(unrequestedPermissionsArray);
        }
  				//将多个Observable结合成一个Observable发射出去
        return Observable.concat(Observable.fromIterable(list));
    }

这里最重要的方法在RxPermissionsFragment这个类中,包括权限的请求、数据回调

void requestPermissions(@NonNull String[] permissions) {
 				//调用系统的请求权限的方法
        requestPermissions(permissions, PERMISSIONS_REQUEST_CODE);
    }

void onRequestPermissionsResult(String permissions[], int[] grantResults, boolean[] shouldShowRequestPermissionRationale) {
        for (int i = 0, size = permissions.length; i < size; i++) {
            PublishSubject<Permission> subject = mSubjects.get(permissions[i]);
            ...
            boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
          //将结果封装成Permission发送出去
            subject.onNext(new Permission(permissions[i], granted, shouldShowRequestPermissionRationale[i]));
        }
    }

到这里我们已经分析完整个request的流程,还剩下requestEach没分析,其实requestEach的流程与上面相似,这里就不作分析了。从整体上来看RxPermissions的流程很简单,但是这里面用到了很多RxJava的操作符,通过监听者模式得到请求结果并发送出去。

总结

  1. 创建一个空的Fragment添加到Activity中
  2. 遍历权限列表,没有请求过权限则通过Fragment调用请求权限的方法
  3. 在Fragment中重写onRequestPermissionsResult方法,并将结果发送出去
  4. 合并Observable数据流

你可能感兴趣的:(源码解析,android,RxPermissions)