在android6.0版本以上,对系统权限的获取需要程序员在代码中动态请求,在用户准许后方可获得此权限。 如果是针对单一的权限申请,那么直接按照谷歌官方的demo直接请求获取即可,但是在项目中往往会涉及到多个权限申请, 此时就会出现一些和用户的交互需求。 所以在多个权限申请的案例中,我们往往是要构造一个工具类来实现和用户友好的交互。 那么具体情况是这样的: 1、进入主activity时申请所有的权限,依次申请。 2、当用户拒绝某个权限后,下次进入主activity中时会再次申请权限。 3、权限被拒绝后下次进入并提示时,会有不再提示勾选框。 4、当不再提示被勾选并且用户拒绝后,则下次进入时要手动引导用户去设置权限。
/**
- 权限控制工具类:
- 为了适配API23,即Android M 在清单文件中配置use permissions后,还要在程序运行的时候进行申请。
- ***整个权限的申请与处理的过程是这样的:
- *****1.进入主Activity,首先申请所有的权限;
- *****2.用户对权限进行授权,有2种情况:
- ********1).用户Allow了权限,则表示该权限已经被授权,无须其它操作;
- ********2).用户Deny了权限,则下次启动Activity会再次弹出系统的Permisssions申请授权对话框。
- *****3.如果用户Deny了权限,那么下次再次进入Activity,会再次申请权限,这次的权限对话框上,会有一个选项“never ask again”:
- ********1).如果用户勾选了“never ask again”的checkbox,下次启动时就必须自己写Dialog或者Snackbar引导用户到应用设置里面去手动授予权限;
- ********2).如果用户未勾选上面的选项,若选择了Allow,则表示该权限已经被授权,无须其它操作;
- ********3).如果用户未勾选上面的选项,若选择了Deny,则下次启动Activity会再次弹出系统的Permisssions申请授权对话框。 */ public class PermissionsUtil {
// 状态码、标志位 private static final int REQUEST_STATUS_CODE = 0x001; private static final int REQUEST_PERMISSION_SETTING = 0x002;
//常量字符串数组,将需要申请的权限写进去,同时必须要在Androidmanifest.xml中声明。 private static String[] PERMISSIONS_GROUP = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.INTERNET, Manifest.permission.CAMERA, Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.ACCESS_WIFI_STATE, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_CONTACTS };
public static void checkAndRequestPermissions(final Activity activity) {
// 一个list,用来存放没有被授权的权限
ArrayList<String> denidArray = new ArrayList<>();
// 遍历PERMISSIONS_GROUP,将没有被授权的权限存放进denidArray
for (String permission : PERMISSIONS_GROUP) {
int grantCode = ActivityCompat.checkSelfPermission(activity, permission);
if (grantCode == PackageManager.PERMISSION_DENIED) {
denidArray.add(permission);
}
}
// 将denidArray转化为字符串数组,方便下面调用requestPermissions来请求授权
String[] denidPermissions = denidArray.toArray(new String[denidArray.size()]);
// 如果该字符串数组长度大于0,说明有未被授权的权限
if (denidPermissions.length > 0) {
// 遍历denidArray,用showRationaleUI来判断,每一个没有得到授权的权限是否是用户手动拒绝的
for (String permission : denidArray) {
// 如果permission是用户手动拒绝的,则用SnackBar来引导用户进入App设置页面,手动授予权限
if (!showRationaleUI(activity, permission)) {
// 判断App是否是首次启动
if (!isAppFirstRun(activity)) {
Snackbar snackbar =
Snackbar.make(activity.findViewById(R.id.btn_sdcard_avail), "这次是真的需要去授权了",
Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("前往设置", new View.OnClickListener() {
@Override public void onClick(View v) {
// 进入App设置页面
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
activity.startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
}
});
snackbar.show();
}
}
break;
}
requestPermissions(activity, denidPermissions);
}
}
/**
- 关于shouldShowRequestPermissionRationale函数的一点儿注意事项:
- ***1).应用安装后第一次访问,则直接返回false;
- ***2).第一次请求权限时,用户Deny了,再次调用shouldShowRequestPermissionRationale(),则返回true;
- ***3).第二次请求权限时,用户Deny了,并选择了“never ask again”的选项时,再次调用shouldShowRequestPermissionRationale()时,返回false;
- ***4).设备的系统设置中,禁止了应用获取这个权限的授权,则调用shouldShowRequestPermissionRationale(),返回false。 */ public static boolean showRationaleUI(Activity activity, String permission) { return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission); }
/**
- 对权限字符串数组中的所有权限进行申请授权,如果用户选择了“never ask again”,则不会弹出系统的Permission申请授权对话框 */ public static void requestPermissions(Activity activity, String[] permissions) { ActivityCompat.requestPermissions(activity, permissions, REQUEST_STATUS_CODE); }
/**
- 用来判断,App是否是首次启动:
- ***由于每次调用shouldShowRequestPermissionRationale得到的结果因情况而变,因此必须判断一下App是否首次启动,才能控制好出现Dialog和SnackBar的时机 */ public static boolean isAppFirstRun(Activity activity) { SharedPreferences sp = activity.getSharedPreferences("config", Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit();
if (sp.getBoolean("first_run", true)) {
editor.putBoolean("first_run", false);
editor.commit();
return true;
} else {
editor.putBoolean("first_run", false);
editor.commit();
return false;
}
} } 可参考博客:http://sunjiajia.com/2016/04/19/android-m-permissions/