傳說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()方法裏,這樣在啓動界面的時候,會先檢測權限信息。