您的位置:首页 > 移动开发 > Android开发

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中,系统新增了部分权限的运行时动态获取。而不再是在以前的版本中安装的时候授予权限。

这里我先给出例子(很晚了要睡了第二天分析源码)

首先是申请

//这个请求事件我写在点击事件里面,
//点击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