android6.0之前,所有的权限都要求同意之后,app才能被安装。6.0之后,动态权限申请很好的处理了之前的强制行为,对用户更加的友好。
新的权限机制,将权限分为两大类,一种普通权限,一种为危险权限。普通权限,在manifest中申请后,无需再主动申请;危险权限,除了在manifest中申请,还需要主动调用API进行动态申请。如果你未在manifest中写明危险权限,即时通过API进行主动申请,也是无效的。
针对新的权限机制,我们需要对权限有个简单的封装,方便我们在项目中使用。
封装方法如下:
/**
* 标准权限检查方法
* 检查所有的权限,对未拥有的权限进行主动申请。对已被拒绝的权限,回调处理。
* @param permissions
*/
public static void checkPermissions(Activity activity, int requestCode,OnDeniedListener listener, String... permissions) {
//用于记录未授权的权限列表。
ArrayList<String> deniedPermissions = new ArrayList<>();
for (String permission : permissions) {
//检测未授权的权限列表
if (ActivityCompat.checkSelfPermission(activity, permission) == PERMISSION_DENIED) {
//添加到权限集合中
deniedPermissions.add(permission);
}
}
//遍历未拥有的权限
for (String permission : deniedPermissions) {
//如果该用户已经点击不再提醒或拒绝,那么返回true,说明用户不想看到提醒权限。
boolean res = ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
if (res) {
Logger.i(permission + "");
// 提示用户未开启权限,说明为什么要开启权限。然后引导用户跳转系统权限设置界面。可以指定permission进行处理
if(listener!=null)
listener.onDenied(permission);
return;
}
}
String[] ps = deniedPermissions.toArray(new String[deniedPermissions.size()]);
if (ps.length > 0)
ActivityCompat.requestPermissions(activity, ps, requestCode);
}
//检测到用户有权限被拒绝不再提醒,进行回调
public interface OnDeniedListener{
void onDenied(String permission);
}
这种写法中,判断了shouldShowRequestPermissionRationale。这个方法作用是什么?
我们看源码说明(蹩脚的英语翻译):
得到一个返回值,表示你是否应该向申请的权限展示原理。如果你还没有该权限,并且你还没有明确地向用户表现出用户同意该权限后的好处,你都应该调用该方法。
例如,你编写了一个照相app,请求相机权限在用户的意料之中,不用解释为什么需要这个权限。然而,这个app还需要通过定位标识照片,一个不懂技术的用户就想知道这个定位和拍照有什么关系。这种情况下,你可能需要选择展示该权限的基本原理。
/**
* Gets whether you should show UI with rationale for requesting a permission.
* You should do this only if you do not have the permission and the context in
* which the permission is requested does not clearly communicate to the user
* what would be the benefit from granting this permission.
* <p>
* For example, if you write a camera app, requesting the camera permission
* would be expected by the user and no rationale for why it is requested is
* needed. If however, the app needs location for tagging photos then a non-tech
* savvy user may wonder how location is related to taking photos. In this case
* you may choose to show UI with rationale of requesting this permission.
* </p>
*
* @param activity The target activity.
* @param permission A permission your app wants to request.
* @return Whether you can show permission rationale UI.
*
* @see #checkSelfPermission(android.content.Context, String)
* @see #requestPermissions(android.app.Activity, String[], int)
*/
public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity,
@NonNull String permission) {
if (Build.VERSION.SDK_INT >= 23) {
return activity.shouldShowRequestPermissionRationale(permission);
}
return false;
}
危险权限列表:
权限组概念:同一权限组中,如果已有一项危险权限被授权,则同一组的其他权限系统会立即授予该权限,而无需与用户进行任何交互。
注意:经过实践测试,权限组中更危险的权限申请后,才会直接获得其他权限。怎么理解这句话?比如定位权限,如果你申请了FINE权限,则直接就拥有COARSE权限;如果你只申请了COARSE权限,则还没有FINE权限,你必须要手动再申请FINE权限,但这时不需要用户同意就直接获取了FINE权限(如果都没申请,是需要用户手动点确认的)。还有读写存储权限也是一样。
虽然都是简单的东西,记录下来,能方便自己查看。