一直以来,Android 6.0以上动态权限申请是一件挺麻烦的事情,网上也有各种方法,和第三方框架提供,但是用起来,有时候还是感觉比较麻烦,但是自从出现了RxPermissions 这个权限框架后, 申请权限变得简单易行!
RxPermissions github地址:GitHub - tbruyelle/RxPermissions: Android runtime permissions powered by RxJava2
1.添加RxPermissions依赖(如果同步失败,可能是因为公司的网络有好多情况下连不到Google的仓库,需要设置镜像代理,具体步骤请查看博客Android Studio 设置阿里云镜像代理(如果设置之后还是远程仓库下载失败,请仔细阅读其内容就可以解决了)_ErwinNakajima的博客-CSDN博客_android studio 阿里云)。
//rxpermissions框架導入
api 'com.github.tbruyelle:rxpermissions:0.11'
使用RxPermissions必须搭配RxJava 使用
//rxjava2框架導入
api 'io.reactivex.rxjava2:rxjava:2.2.10'
api 'io.reactivex.rxjava2:rxandroid:2.1.1'
使用RxPermissions搭配RxLifecycle3
//1.解决rxjava导致的内存泄漏的框架導入
api 'com.trello.rxlifecycle3:rxlifecycle:3.1.0'
// If you want to bind to Android-specific lifecycles
api 'com.trello.rxlifecycle3:rxlifecycle-android:3.1.0'
// If you want pre-written Activities and Fragments you can subclass as providers
api 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'
// If you want pre-written support preference Fragments you can subclass as providers
api 'com.trello.rxlifecycle3:rxlifecycle-components-preference:3.1.0'
// If you want to use Android Lifecycle for providers
api 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.1.0'
// If you want to use Kotlin syntax
api 'com.trello.rxlifecycle3:rxlifecycle-kotlin:3.1.0'
// If you want to use Kotlin syntax with Android Lifecycle
api 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle-kotlin:3.1.0'
// If you want to use Navi for providers
// DEPRECATED: Use rxlifecycle-android-lifecycle instead. This will be removed in a future release.
api 'com.trello.rxlifecycle3:rxlifecycle-navi:3.1.0'
2.在AndroidManifest.xml中添加自己需要用到的权限。
<!-- 读取SD卡,用于更换头像,取SD卡取照片 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<!-- 允许读取手机状态的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission
android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
3.权限请求回调接口。
package com.phone.common_library.callback;
public interface OnCommonRxPermissionsCallback {
/**
* 所有的权限都授予
*/
void onRxPermissionsAllPass();
/**
* 至少一个权限未授予且未勾选不再提示
*/
void onNotCheckNoMorePromptError();
/**
* 至少一个权限未授予且勾选了不再提示
*/
void onCheckNoMorePromptError();
}
4.权限请求管理类。
package com.phone.common_library.manager;
import com.phone.common_library.callback.OnCommonRxPermissionsCallback;
import com.tbruyelle.rxpermissions2.Permission;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.trello.rxlifecycle3.android.ActivityEvent;
import com.trello.rxlifecycle3.android.FragmentEvent;
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;
import com.trello.rxlifecycle3.components.support.RxFragment;
import io.reactivex.functions.Consumer;
public class RxPermissionsManager {
private static final String TAG = RxPermissionsManager.class.getSimpleName();
private static RxPermissionsManager rxPermissionsManager;
// private RxPermissions rxPermissions;
private RxPermissions rxActivityPermissions;
private RxPermissions rxFragmentPermissions;
// private RxPermissionsManager() {
// }
public static RxPermissionsManager getInstance() {
if (rxPermissionsManager == null) {
synchronized (RxPermissionsManager.class) {
if (rxPermissionsManager == null) {
rxPermissionsManager = new RxPermissionsManager();
}
}
}
return rxPermissionsManager;
}
/**
* RxAppCompatActivity里需要的时候直接调用就行了(不會拋出異常)
*/
public void initRxPermissionsRxAppCompatActivity(RxAppCompatActivity rxAppCompatActivity, String[] permissions, OnCommonRxPermissionsCallback onCommonRxPermissionsCallback) {
rxActivityPermissions = new RxPermissions(rxAppCompatActivity);
rxActivityPermissions
.requestEachCombined(permissions)
//解决rxjava导致的内存泄漏问题
.compose(rxAppCompatActivity.<Permission>bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(new Consumer<Permission>() {
@Override
public void accept(Permission permission) throws Exception {
if (permission.granted) {
// `permission.name` is granted !
// 所有的权限都授予
LogManager.i(TAG, "所有的权限都授予");
LogManager.i(TAG, "所有的权限都授予 permission.name*****" + permission.name);
// Intent bindIntent = new Intent(this, Base64AndFileService.class);
// // 绑定服务和活动,之后活动就可以去调服务的方法了
// bindService(bindIntent, connection, BIND_AUTO_CREATE);
onCommonRxPermissionsCallback.onRxPermissionsAllPass();
} else if (permission.shouldShowRequestPermissionRationale) {
// Denied permission without ask never again
// 至少一个权限未授予且未勾选不再提示
LogManager.i(TAG, "至少一个权限未授予且未勾选不再提示");
onCommonRxPermissionsCallback.onNotCheckNoMorePromptError();
} else {
// Denied permission with ask never again
// Need to go to the settings
// 至少一个权限未授予且勾选了不再提示
LogManager.i(TAG, "至少一个权限未授予且勾选了不再提示");
onCommonRxPermissionsCallback.onCheckNoMorePromptError();
}
}
});
}
/**
* RxFragment里需要的时候直接调用就行了(不會拋出異常)
*/
public void initRxPermissionsRxFragment(RxFragment rxFragment, String[] permissions, OnCommonRxPermissionsCallback onCommonRxPermissionsCallback) {
rxFragmentPermissions = new RxPermissions(rxFragment);
rxFragmentPermissions
.requestEachCombined(permissions)
//解决rxjava导致的内存泄漏问题
.compose(rxFragment.<Permission>bindUntilEvent(FragmentEvent.DESTROY))
.subscribe(new Consumer<Permission>() {
@Override
public void accept(Permission permission) throws Exception {
if (permission.granted) {
// `permission.name` is granted !
// 所有的权限都授予
LogManager.i(TAG, "所有的权限都授予");
LogManager.i(TAG, "所有的权限都授予 permission.name*****" + permission.name);
// Intent bindIntent = new Intent(this, Base64AndFileService.class);
// // 绑定服务和活动,之后活动就可以去调服务的方法了
// bindService(bindIntent, connection, BIND_AUTO_CREATE);
onCommonRxPermissionsCallback.onRxPermissionsAllPass();
} else if (permission.shouldShowRequestPermissionRationale) {
// Denied permission without ask never again
// 至少一个权限未授予且未勾选不再提示
LogManager.i(TAG, "至少一个权限未授予且未勾选不再提示");
onCommonRxPermissionsCallback.onNotCheckNoMorePromptError();
} else {
// Denied permission with ask never again
// Need to go to the settings
// 至少一个权限未授予且勾选了不再提示
LogManager.i(TAG, "至少一个权限未授予且勾选了不再提示");
onCommonRxPermissionsCallback.onCheckNoMorePromptError();
}
}
});
}
}
5.在RxAppCompatActivity(需要让自己的Activity继承RxAppCompatActivity)中的使用。
private AlertDialog mPermissionsDialog;
private String[] permissions = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE};
/**
* 請求權限,RxAppCompatActivity里需要的时候直接调用就行了
*/
private void initRxPermissionsRxAppCompatActivity() {
RxPermissionsManager rxPermissionsManager = RxPermissionsManager.getInstance();
rxPermissionsManager.initRxPermissionsRxAppCompatActivity(this, permissions, new OnCommonRxPermissionsCallback() {
@Override
public void onRxPermissionsAllPass() {
//所有的权限都授予
}
@Override
public void onNotCheckNoMorePromptError() {
//至少一个权限未授予且未勾选不再提示
showSystemSetupDialog();
}
@Override
public void onCheckNoMorePromptError() {
//至少一个权限未授予且勾选了不再提示
showSystemSetupDialog();
}
});
}
private void showSystemSetupDialog() {
cancelPermissionsDialog();
if (mPermissionsDialog == null) {
mPermissionsDialog = new AlertDialog.Builder(this)
.setTitle("权限设置")
.setMessage("获取相关权限失败,将导致部分功能无法正常使用,请到设置页面手动授权")
.setPositiveButton("去授权", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
cancelPermissionsDialog();
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getApplicationContext().getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 207);
}
})
.create();
}
mPermissionsDialog.setCancelable(false);
mPermissionsDialog.setCanceledOnTouchOutside(false);
mPermissionsDialog.show();
}
/**
* 关闭对话框
*/
private void cancelPermissionsDialog() {
if (mPermissionsDialog != null) {
mPermissionsDialog.cancel();
mPermissionsDialog = null;
}
}
6.在RxFragment(需要让自己的Activity继承RxFragment)中的使用。
private AlertDialog mPermissionsDialog;
private String[] permissions = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE};
/**
* RxFragment里需要的时候直接调用就行了
*/
private void initRxPermissionsRxFragment() {
RxPermissionsManager rxPermissionsManager = RxPermissionsManager.getInstance();
rxPermissionsManager.initRxPermissionsRxFragment(this, permissions, new OnCommonRxPermissionsCallback() {
@Override
public void onRxPermissionsAllPass() {
//所有的权限都授予
}
@Override
public void onNotCheckNoMorePromptError() {
//至少一个权限未授予且未勾选不再提示
showSystemSetupDialog();
}
@Override
public void onCheckNoMorePromptError() {
//至少一个权限未授予且勾选了不再提示
showSystemSetupDialog();
}
});
}
private void showSystemSetupDialog() {
cancelPermissionsDialog();
if (mPermissionsDialog == null) {
mPermissionsDialog = new AlertDialog.Builder(rxAppCompatActivity)
.setTitle("权限设置")
.setMessage("获取相关权限失败,将导致部分功能无法正常使用,请到设置页面手动授权")
.setPositiveButton("去授权", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
cancelPermissionsDialog();
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", rxAppCompatActivity.getApplicationContext().getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 207);
}
})
.create();
}
mPermissionsDialog.setCancelable(false);
mPermissionsDialog.setCanceledOnTouchOutside(false);
mPermissionsDialog.show();
}
/**
* 关闭对话框
*/
private void cancelPermissionsDialog() {
if (mPermissionsDialog != null) {
mPermissionsDialog.cancel();
mPermissionsDialog = null;
}
}