Android基础知识---RxPermissions获取运行时权限
2017-05-01 23:36
579 查看
大家都了解android6.0的运行时权限分为两类:
一类是Normal Permissions,这类权限不涉及个人隐私,不需要用户进行授权,比如手机震动,访问网络;
一类是Dangerous Permissions,这类权限涉及个人隐私,需要用户进行授权,比如读取SD卡,访问通讯录等。
如果是Dangerous Permissions这种权限需要我申请权限,这里我写过例子你们可以看看例子
当然这样是很不方便的所以这里介绍RxPermissions。
一、简介
RxPermissions是基于RxJava开发的用于帮助在Android 6.0中处理运行时权限检测的框架。在Android 6.0中,系统新增了部分权限的运行时动态获取。而不再是在以前的版本中安装的时候授予权限。
这里我先给出例子(很晚了要睡了第二天分析源码)
首先是申请
同时请求多个权限若有一个权限未成功则返回false。
分别申请多个权限
注意:由于在请求权限的过程中app有可能会被重启,所以权限请求必须放在初始化的阶段,比如在Activity.onCreate/onResume, 或者
View.onFinishInflate方法中。如果不这样处理,那么如果app在请求过程中重启的话,权限请求结果将不会发送给订阅者即subscriber。(就比如我们申请时候人为,以及其他原因导致的重启)
我们来分析request(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)的实现
我们主要看看ensure(permissions)方法的实现
我们可以看到在call()方法里调用了request(o, permissions)方法
首先对permissions做了判断,然后调用了oneOf(trigger, pending(permissions))方法,并通过flatMap()操作符在call()方法中调用了request_(permissions);
然后我们来看看request_(permissions)
代码如上,注释非常清晰,整体上就是将已经允许的权限和已经拒绝过的权限添加到list中,并且将还未请求的权限分别添加到mSubjects与list中。然后调用startShadowActivity();方法。最后通过Observable.concat(Observable.from(list));返回
这里就简单说下如果你对Rxjava不熟悉建议先看看Rxjava
一类是Normal Permissions,这类权限不涉及个人隐私,不需要用户进行授权,比如手机震动,访问网络;
一类是Dangerous Permissions,这类权限涉及个人隐私,需要用户进行授权,比如读取SD卡,访问通讯录等。
如果是Dangerous Permissions这种权限需要我申请权限,这里我写过例子你们可以看看例子
当然这样是很不方便的所以这里介绍RxPermissions。
一、简介
RxPermissions是基于RxJava开发的用于帮助在Android 6.0中处理运行时权限检测的框架。在Android 6.0中,系统新增了部分权限的运行时动态获取。而不再是在以前的版本中安装的时候授予权限。
这里我先给出例子(很晚了要睡了第二天分析源码)
首先是申请
//这个请求事件我写在点击事件里面, //点击button之后RxPermissions会为我们申请运行时权限 RxPermissions.getInstance(MainActivity.this) .request(Manifest.permission.READ_CALENDAR)//这里填写所需要的权限 .subscribe(new Action1<Boolean>() { @Override public void call(Boolean aBoolean) { if (aBoolean) {//true表示获取权限成功(注意这里在android6.0以下默认为true) Log.i("权限", Manifest.permission.READ_CALENDAR + ":" + "获取成功"); } else { Log.i("权限", Manifest.permission.READ_CALENDAR + ":" + "获取失败"); } } });
同时请求多个权限若有一个权限未成功则返回false。
//同时请求多个权限若有一个权限未成功则返回false。 RxPermissions.getInstance(MainActivity.this) .request(Manifest.permission.RECEIVE_MMS, Manifest.permission.WRITE_EXTERNAL_STORAGE)//多个权限用","隔开 .subscribe(new Action1<Boolean>() { @Override public void call(Boolean aBoolean) { if (aBoolean) { //当所有权限都允许之后,返回true Log.i("权限", "btn_more_sametime:" + aBoolean); } else { //只要有一个权限禁止,返回false, //下一次申请只申请没通过申请的权限 Log.i("权限", "btn_more_sametime:" + aBoolean); } } });
分别申请多个权限
//分别申请多个权限 RxPermissions.getInstance(MainActivity.this) //分别申请多个权限时,使用requestEach .requestEach(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE) .subscribe(new Action1<Permission>() { @Override public void call(Permission permission) { if (permission.name.equals(Manifest.permission.ACCESS_FINE_LOCATION)) { //当ACCESS_FINE_LOCATION权限获取成功时,permission.granted=true Log.i("权限", Manifest.permission.ACCESS_FINE_LOCATION + ":" + permission.granted); } if (permission.name.equals(Manifest.permission.RECORD_AUDIO)) { //当RECORD_AUDIO 权限获取成功时,permission.granted=true Log.i("权限", Manifest.permission.RECORD_AUDIO + ":" + permission.granted); } if (permission.name.equals(Manifest.permission.CAMERA)) { //当CAMERA权限获取成功时,permission.granted=true Log.i("权限", Manifest.permission.CAMERA + ":" + permission.granted); } } });
注意:由于在请求权限的过程中app有可能会被重启,所以权限请求必须放在初始化的阶段,比如在Activity.onCreate/onResume, 或者
View.onFinishInflate方法中。如果不这样处理,那么如果app在请求过程中重启的话,权限请求结果将不会发送给订阅者即subscriber。(就比如我们申请时候人为,以及其他原因导致的重启)
我们来分析request(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)的实现
public Observable<Boolean> request(final String... permissions) { return Observable.just(null).compose(ensure(permissions)); }
我们主要看看ensure(permissions)方法的实现
public Observable.Transformer<Object, Boolean> ensure(final String... permissions) { //创建一个Transformer对象返回 return new Observable.Transformer<Object, Boolean>() { // o表示当前Observable对象。 @Override public Observable<Boolean> call(Observable<Object> o) { //request(o, permissions) 方法返回 Observable<Permission>对象 return request(o, permissions) // 将Observable<Permission>转换为Observable<Boolean> // buffer操作符 .buffer(permissions.length) // flatMap操作符 .flatMap(new Func1<List<Permission>, Observable<Boolean>>() { @Override public Observable<Boolean> call(List<Permission> permissions) { // 如果permissions为空那么直接返回Observable.empty(); if (permissions.isEmpty()) { // Occurs during orientation change, when the subject receives onComplete. // In that case we don't want to propagate that empty list to the // subscriber, only the onComplete. return Observable.empty(); } // 遍历所有Permission,如果有一个未成功则返回false,全部成功返回true。 for (Permission p : permissions) { if (!p.granted) { return Observable.just(false); } } return Observable.just(true); } }); } }; }
我们可以看到在call()方法里调用了request(o, permissions)方法
private Observable<Permission> request(final Observable<?> trigger, final String... permissions) { //如果并没有请求的权限则抛出异常 if (permissions == null || permissions.length == 0) { throw new IllegalArgumentException("RxPermissions.request/requestEach requires at least one input permission"); } return oneOf(trigger, pending(permissions)) .flatMap(new Func1<Object, Observable<Permission>>() { @Override public Observable<Permission> call(Object o) { return request_(permissions); } }); }
首先对permissions做了判断,然后调用了oneOf(trigger, pending(permissions))方法,并通过flatMap()操作符在call()方法中调用了request_(permissions);
然后我们来看看request_(permissions)
@TargetApi(Build.VERSION_CODES.M) private Observable<Permission> request_(final String... permissions) { //创建出一个存放Observable<Permission>的list List<Observable<Permission>> list = new ArrayList<>(permissions.length); //存放还为请求权限的list List<String> unrequestedPermissions = new ArrayList<>(); // 在请求多个权限的时候,我们为每一个请求的权限都创建一个observable对象,在最后 // 这些observable会被合并成一个response。 for (String permission : permissions) { log("Requesting permission " + permission); //如果是已经获得的权限,或者Android版本在6.0之前则直接添加一个 // Observable.just(new Permission(permission, true))对象. if (isGranted(permission)) { // Already granted, or not Android M // Return a granted Permission object. list.add(Observable.just(new Permission(permission, true))); continue; } // 如果是已经拒绝的权限则添加 // Observable.just(new Permission(permission, false))对象. if (isRevoked(permission)) { // Revoked by a policy, return a denied Permission object. list.add(Observable.just(new Permission(permission, false))); continue; } PublishSubject<Permission> subject = mSubjects.get(permission); // 如果mSubjects 不存在当前 permission,则添加到unrequestedPermissions中 // 并且创建PublishSubject对象并添加到mSubjects中。 if (subject == null) { unrequestedPermissions.add(permission); subject = PublishSubject.create(); mSubjects.put(permission, subject); } //并且添加到list中 list.add(subject); } //如果有未请求的权限 if (!unrequestedPermissions.isEmpty()) { startShadowActivity(unrequestedPermissions .toArray(new String[unrequestedPermissions.size()])); } return Observable.concat(Observable.from(list)); } void startShadowActivity(String[] permissions) { log("startShadowActivity " + TextUtils.join(", ", permissions)); Intent intent = new Intent(mCtx, ShadowActivity.class); intent.putExtra("permissions", permissions); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mCtx.startActivity(intent); }
代码如上,注释非常清晰,整体上就是将已经允许的权限和已经拒绝过的权限添加到list中,并且将还未请求的权限分别添加到mSubjects与list中。然后调用startShadowActivity();方法。最后通过Observable.concat(Observable.from(list));返回
这里就简单说下如果你对Rxjava不熟悉建议先看看Rxjava
相关文章推荐
- Android动态获取运行时权限RxPermissions
- android——RxPermissions获取运行时权限
- Android动态获取运行时权限RxPermissions
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取
- RxPermissions解决Android 6.0 获取运行权限问题
- Android基础知识积累之手机获取屏幕宽度高度
- 【Android基础知识】网络获取Xml文件并解析
- Neither user 10155 nor current process has android.permission.ACCESS_COARSE_LOCATION. 权限意见添加,运行时无法获取
- Android_基础知识_03_获取屏幕的高度和宽度
- Android6.0使用RxPermissions获取运行时权限
- Android基础知识--12.权限系统
- Android 6.0运行时权限获取
- android 安全讲座第三层 linux权限基础知识
- Android 6.0 运行时权限 easypermissions,permissionsdispatcher ,rxpermissions 的实现
- RxPermissions 获取运行时权限
- [android基础知识] 之十七: Android手机获取唯一物理标识
- Android之运行时相机权限和联系人权限获取
- Android基础知识之Manifest文件中的用户权限元素
- Android基础知识之apk签名权限