注:本文主要是梳理一下Android动态权限申请的一个基本套路。
需要有一定的Android编码经验,对于完全的新手来说,可能还有些技术细节没有做具体解释。
附上一个基本的Demo代码链接:android-permission-request-demo
Android动态权限申请有效保证了用户的的安全,但是对开发者来说需要写跟多的代码逻辑来跟用户确认权限。
先不考虑代码,我们通过官方文档的描述来梳理一下整个权限处理的流程,如下图:
从上图可以看出,整个过程始于“权限检查”,归集于“授权回调”。
也就是说,除非本身就具备了相关权限,否则我们所有的后续操作都需要从授权回调开始往下走。
只是从授权回调往下走的时候,需要根据前面流程所形成的的条件,进行不同的操作。
从图中可以看出总共有三类分支(分别用红、黄、绿三色标注):
1、用户允许授权。
2、用户禁止授权,且点击了“不再提示”复选框。
3、用户禁止授权,但是没有点击“不再提示”复选框。
那么接下来我们就从这三种情况着手,将授权回调的流程继续梳理下去,如下图:
按照谷歌的设计意图,如果用户拒绝了权限,但是没有选择“不再提示”,我们就需要通过对话框等方式向用户解释为什么需要授予权限,然后再次申请权限,弹出授权对话框。
如果用户拒绝了权限,而且选择了“不再提示”,系统就不不会再弹出授权对话框。但是很多权限都是APP运行的基本保证,所以我们还是得想办法解释为什么需要授权,然后引导用户去授权。
我们可以看到,在授权回调函数中时,只要是用户用户已经拒绝了权限,我们都需要弹框向用户进行权限说明。
简洁起见,我们完全可以把上图中两个自定义对话框的形态做到完全一样,只是用户点击授权后的授权不方式不一样而已。
基于以上的完整流程分析,我们就可以设计出相应的代码。
此处以拨电话为例,先回顾一下上图中谷歌的API:
1、检测是否有权限。
// BEGIN 动态权限申请代码段
int hasCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
if (hasCallPhonePermission == PackageManager.PERMISSION_GRANTED) {
// 有权限,执行相关操作
callPhone();
} else {
// 无权限,需要请求权限
...
}
// END
2、请求权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQ);
3、授权回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CALL_PHONE_REQ) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 用户在授权对话框中授予了权限,执行相关操作
callPhone();
} else {
// 没有授权
if (ActivityCompat.shouldShowRequestPermissionRationale(
MainActivity.this, Manifest.permission.CALL_PHONE)) {
// 没有点选“不再提示”
showPermissionDialog(FLAG_REQUEST_PERMISSION);
} else {
// 点选了“不再提示”
showPermissionDialog(FLAG_SETTINGS_PERMISSION);
}
}
}
}
4、弹出包含说明的授权对话框。
private void showPermissionDialog(final int flag) {
new AlertDialog.Builder(this).setTitle("授权提示")
.setMessage("需要授予拨打电话权限才能打电话。")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 用户取消了授权,整个路程结束,不执行任何操作。
Toast.makeText(MainActivity.this, "取消拨打电话", Toast.LENGTH_SHORT).show();
}
})
.setPositiveButton("去授权", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (flag) {
case FLAG_REQUEST_PERMISSION:
// 用户之前没有点击“不再提示”,但是此处选在继续授权的分支
// 请求系统授权对话框
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQ);
break;
case FLAG_SETTINGS_PERMISSION:
// 用户之前点击过“不再提示”,此处选择继续授权的分支
// 到APP的详情页手动授权。
startActivity(getAppDetailSettingIntent());
break;
}
}
}).create().show();
}
5、跳转到当前APP的应用详情页的Intent构造。
private Intent getAppDetailSettingIntent() {
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", getPackageName(), null));
return localIntent;
}
以上,与大家分享,希望能帮不太熟悉的朋友更清晰的梳理动态权限申请的整个流程。