Android6.0以后Google不再允许开发者直接或许应用的权限,需要在用户知情的情况下授予权限,即需要用到权限的时候弹出一个权限提示框。
接下来我们将使用三种方式,完成运行时权限的申请:
为了避免用户没有留意而拒绝了应用的关键权限,我们必须对用户授权时的各种状态进行详细的分析。
用户在授予权限时存在三种状态:
首先在manifest中添加如下4个权限声明,方便之后申请权限。
如果不添加,使用代码申请权限,申请的结果就是默认:拒绝&不再询问。
/**
* 1.判断系统版本
* 2.调用 requestPermissions(权限集合,requestCode);
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(mPermissions,0x001);
}
/**
* 3.申请权限的结果回调
* @param requestCode
* @param mPermissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] mPermissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, mPermissions, grantResults);
}
public interface PermissionInterface {
/**
* 可设置请求权限请求码
*/
int getPermissionsRequestCode();
/**
* 设置需要请求的权限
*/
String[] getPermissions();
/**
* 请求权限成功回调
*/
void requestPermissionsSuccess();
/**
* 请求权限失败回调
*/
void requestPermissionsFail();
}
public class PermissionHelper {
private Activity mActivity;
private PermissionInterface mPermissionInterface;
public PermissionHelper(Activity activity, PermissionInterface permissionInterface) {
mActivity = activity;
mPermissionInterface = permissionInterface;
}
/**
* 开始请求权限。
* 方法内部已经对Android M 或以上版本进行了判断,外部使用不再需要重复判断。
* 如果设备还不是M或以上版本,则也会回调到requestPermissionsSuccess方法。
*/
public void requestPermissions() {
String[] deniedPermissions = PermissionUtil.getDeniedPermissions(mActivity, mPermissionInterface.getPermissions());
if (deniedPermissions != null && deniedPermissions.length > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //Android 6.0及以后才需要运行时获取权限
mActivity.requestPermissions(deniedPermissions, mPermissionInterface.getPermissionsRequestCode());
}
} else {
mPermissionInterface.requestPermissionsSuccess();
}
}
/**
* 在Activity中的onRequestPermissionsResult中调用
*
* @param requestCode
* @param permissions
* @param grantResults
* @return true 代表对该requestCode感兴趣,并已经处理掉了。false 对该requestCode不感兴趣,不处理。
*/
public boolean requestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == mPermissionInterface.getPermissionsRequestCode()) {
boolean isAllGranted = true;//是否全部权限已授权
for (int result : grantResults) {
if (result == PackageManager.PERMISSION_DENIED) {
isAllGranted = false;
break;
}
}
if (isAllGranted) {
//已全部授权
mPermissionInterface.requestPermissionsSuccess();
} else {
//权限有缺失
mPermissionInterface.requestPermissionsFail();
}
return true;
}
return false;
}
}
public class PermissionUtil {
/**
* 检查所需权限中缺少的权限
* 防止权限重复获取
*
* @param context
* @param permissions
* @return 返回缺少的权限,null 意味着没有缺少权限
*/
public static String[] getDeniedPermissions(Context context, String[] permissions) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList<String> deniedPermissionList = new ArrayList<>();
for (String permission : permissions) {
if (context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
deniedPermissionList.add(permission);
}
}
int size = deniedPermissionList.size();
if (size > 0) {
return deniedPermissionList.toArray(new String[deniedPermissionList.size()]);
}
}
return null;
}
/**
* 提醒用户手动设置权限的对话框
*
* @param activity
* @param text
*/
public static void PermissionDialog(final Activity activity, String text) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setCancelable(false);
builder.setMessage(text);
builder.setNegativeButton("算了", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
activity.finish();//没有权限,关闭当前页面
}
});
builder.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//去应用管理界面手动给予权限
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + activity.getPackageName()));
activity.startActivity(intent);
}
});
builder.create().show();
}
/**
* 权限的提示文字
* 可以根据应用需求自行更改
*
* @param perms
* @return
*/
public static String permissionText(String[] perms) {
StringBuilder sb = new StringBuilder();
for (String s : perms) {
if (s.equals(Manifest.permission.CAMERA)) {
sb.append("相机权限(用于拍照,视频聊天);\n");
} else if (s.equals(Manifest.permission.RECORD_AUDIO)) {
sb.append("麦克风权限(用于发语音,语音及视频聊天);\n");
} else if (s.equals(Manifest.permission.READ_EXTERNAL_STORAGE)){
sb.append("读取权限(用于读取数据);\n");
}else if (s.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
sb.append("存储(用于存储必要信息,缓存数据);\n");
}
}
return "程序运行需要如下权限:\n" + sb.toString();
}
}
public class MainActivity extends AppCompatActivity implements PermissionInterface {
//要申请的权限
private String[] mPermissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};
private PermissionHelper permissionHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
permissionHelper = new PermissionHelper(this, this);
//申请权限
permissionHelper.requestPermissions();
}
@Override
public int getPermissionsRequestCode() {
return 0;
}
@Override
public String[] getPermissions() {
return mPermissions;
}
@Override
public void requestPermissionsSuccess() {
//do something
}
@Override
public void requestPermissionsFail() {
StringBuilder sb = new StringBuilder();
mPermissions = PermissionUtil.getDeniedPermissions(this, mPermissions);
for (String s : mPermissions) {
if (s.equals(Manifest.permission.CAMERA)) {
sb.append("相机权限(用于拍照,视频聊天);\n");
} else if (s.equals(Manifest.permission.RECORD_AUDIO)) {
sb.append("麦克风权限(用于发语音,语音及视频聊天);\n");
} else if (s.equals(Manifest.permission.READ_EXTERNAL_STORAGE) || s.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
sb.append("存储,读取权限(用于存储必要信息,缓存数据);\n");
}
}
PermissionUtil.PermissionDialog(this, "程序运行需要如下权限:\n" + sb.toString() + "请在应用权限管理进行设置!");
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] mPermissions, int[] grantResults) {
if (permissionHelper.requestPermissionsResult(requestCode, mPermissions, grantResults)) {
//权限请求结果,并已经处理了该回调
return;
}
super.onRequestPermissionsResult(requestCode, mPermissions, grantResults);
}
}
/**
* Permission check result: this is returned by {@link #checkPermission}
* if the permission has been granted to the given package.
*/
public static final int PERMISSION_GRANTED = 0;
/**
* Permission check result: this is returned by {@link #checkPermission}
* if the permission has not been granted to the given package.
*/
public static final int PERMISSION_DENIED = -1;
所以无法分辨拒绝和拒绝&不再询问两种状态,只能统一算作授权失败统一处理。
Google自己都觉得申请运行时权限太过于麻烦,于是自己写了easypermissions来解决这个问题。
该开源库的GitHub地址为:https://github.com/googlesamples/easypermissions
implementation 'pub.devrel:easypermissions:1.2.0'//简化权限库
/**
* EasyPermissions.PermissionCallbacks 权限获取状态的监听
* EasyPermissions.RationaleCallbacks 权限获取失败后弹出的对话框的[取消,确认]按钮监听
*/
public class Main2Activity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks, EasyPermissions.RationaleCallbacks {
//要申请的权限
private String[] mPermissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};
public static final int CODE = 0x001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
//检查权限,防止重复获取
mPermissions = PermissionUtil.getDeniedPermissions(this, mPermissions);
if (mPermissions.length > 0) {
/**
* 1.上下文
* 2.权限失败后弹出对话框的内容
* 3.requestCode
* 4.要申请的权限
*/
EasyPermissions.requestPermissions(this, PermissionUtil.permissionText(mPermissions), CODE, mPermissions);
}
}
//所有的权限申请成功的回调
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
//do something
}
//权限获取失败的回调
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
//存在被永久拒绝(拒绝&不再询问)的权限
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
mPermissions = PermissionUtil.getDeniedPermissions(this, mPermissions);
PermissionUtil.PermissionDialog(this, PermissionUtil.permissionText(mPermissions) + "请在应用权限管理进行设置!");
} else {
EasyPermissions.requestPermissions(this, PermissionUtil.permissionText(mPermissions), CODE, mPermissions);
}
}
//权限被拒绝后的显示提示对话框,点击确认的回调
@Override
public void onRationaleAccepted(int requestCode) {
//会自动再次获取没有申请成功的权限
//do something
}
//权限被拒绝后的显示提示对话框,点击取消的回调
@Override
public void onRationaleDenied(int requestCode) {
//什么都不会做
//do something
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//将结果传入EasyPermissions中
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
}
结合RxJava的运行时权限请求库,必须结合RxJava使用,使用及其简单。
GitHub:https://github.com/tbruyelle/RxPermissions
implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'
implementation 'io.reactivex.rxjava2:rxjava:2.1.9'
RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
rxPermissions.requestEach(mPermissions).subscribe(new Consumer<Permission>() {
@Override
public void accept(Permission permission) {
Log.i(TAG, "accept: " + permission.toString());
if (permission.granted) {
//权限获取成功
} else if (permission.shouldShowRequestPermissionRationale) {
//权限获取失败,但是没有永久拒绝
} else {
//权限获取失败,而且被永久拒绝
}
}
});
GitHub: https://github.com/MyAndroidDemo/PermissionDemo