传说Android 7.0的市场占有率终于1%了,Android 6.0基本上人人有了。这个时候,我不得不把软件开发的SDK目标版本提升到了23。这是就要考虑实现权限的动态分配了。基于我项目用使用了RxJava,所以我就选择了RxPermissions框架来实现权限的动态分配。
一、了解权限
权限分两种:普通权限、危险权限。普通权限在AndroidManifest.xml声明就可以了,危险权限在AndroidManifest.xml声明之后,还需要在软件运行的时候,动态的获取。目前危险权限一共有26个,其他的都是普通权限。
Dangerous Permissions 共有26个:
group:android.permission-group.CAMERA
permission:android.permission.CAMERAgroup:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORSgroup:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIOgroup:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDARgroup:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATIONgroup:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGEgroup:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTSgroup:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTSgroup:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAILandroid.permission.ANSWER_PHONE_CALLS
一共九大分组,每个分组只要申请其中一个权限,其他权限都可以获得。最后一个是Android 8.0新添加的权限,是限制接听来电的权限。如果想查看其他权限可以查看访问权限API。
二、RxPermissions
在GitHub上的地址是:https://github.com/tbruyelle/RxPermissions。
现在主要有两个分支,如下图:
2.x分支是基于RxJava2的源码。master是基于Rxjava的源码。不管是RxJava、RxJava2对RxPermissions的使用没有影响,只是导入的依赖不一样。
RxJava、RxJava2导入的依赖分别是:
compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar'
compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.4@aar'
RxPermissions的使用
1、minSdkVersion 必须大于等于11.
2、在build.gradle中配置。
如果没有的话,添加这个。
android {
repositories {
jcenter() // If not already there
}
}
再添加依赖:
基于RxJava
dependencies {
compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar'
}
基于RxJava2
dependencies {
compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar'
}
3、初始化
RxPermissions rxPermissions = RxPermissions.getInstance(this);
4、使用方法
申请一个权限的方法:
// 假如申请调用系统拍照
rxPermissions.request(Manifest.permission.CAMERA)
.subscribe(new Subscriber<Boolean>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Boolean aBoolean) {
// aBoolean:true开启成功 false开启失败
}
});
申请多个权限的方法:
rxPermissions.request(Manifest.permission.CAMERA,
Manifest.permission.ACCESS_FINE_LOCATION)
.subscribe(new Subscriber<Boolean>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Boolean aBoolean) {
// aBoolean:true开启成功 false开启失败
// 只要有一个权限申请失败,就返回false
}
});
申请权限并查看申请结果的详细信息:
rxPermissions.requestEach(permissions)
.subscribe(new Subscriber<Permission>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Permission permission) {
if (permission.granted) {
Log.e("申请成功:",permission.name);
} else if (permission.shouldShowRequestPermissionRationale) {
Log.e("申请取消:",permission.name);
} else {
Log.e("申请失败:",permission.name);
}
}
});
这个方法,是实现返回每个权限申请的结果。返回的是Permission 类。包含权限申请结果,包含:permission.granted表示申请成功;permission.shouldShowRequestPermissionRationale表示申请取消;如果这两个都不是,表示申请被拒绝,只能在设置界面手动开启。跳转至系统设置界面的方法:
/**
* 获取应用详情页面intent
*/
private void getAppDetailSettingIntent() {
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", getPackageName(), null));
} else {
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
localIntent.putExtra("com.android.settings.ApplicationPkgName", getPackageName());
}
startActivity(localIntent);
mContext.overridePendingTransitionEnter();
}
github还提到了ensure、ensureEach 方法。也分别对应了返回的简单结果和详细结果。这两个方法是实现view绑定权限请求的框架RxBinding时使用的,RxBinding是要结合RxPermission使用的。RxBinding的GitHub地址
权限的请求方法,最好写在onCreate()方法里,这样在启动界面的时候,会先检测权限信息。