一.序
在之前的文章聊聊Android M 6.0 的运行时权限曾提到过,Google Play开发者明年势必要努力将targetsdkversion升级到26的过程中。官网的文档:向 Android 8.0 迁移应用 已经给大家了一个升级指南。当然动态权限也是需要关注的一部分。可能有部分开发者已经将targetsdkversion升级到23了。可是当targetsdkversion升级到26的时候,同样因为API的改动,也许会遇到问题。本文来介绍一下。这其中会遇到的问题。以及解决方案。
二.Android O(8.0)运行时权限策略变化
借用官网的文档
权限
在 Android 8.0 之前,如果应用在运行时请求权限并且被授予该权限,系统会错误地将属于同一权限组并且在清单中注册的其他权限也一起授予应用。
对于针对 Android 8.0 的应用,此行为已被纠正。系统只会授予应用明确请求的权限。然而,一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准。
例如,假设某个应用在其清单中列出 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE。应用请求 READ_EXTERNAL_STORAGE,并且用户授予了该权限。如果该应用针对的是 API 级别 24 或更低级别,系统还会同时授予 WRITE_EXTERNAL_STORAGE,因为该权限也属于同一 STORAGE 权限组并且也在清单中注册过。如果该应用针对的是 Android 8.0,则系统此时仅会授予 READ_EXTERNAL_STORAGE;不过,如果该应用后来又请求 WRITE_EXTERNAL_STORAGE,则系统会立即授予该权限,而不会提示用户。
总结:
- 以前,申请一个子权限会自动获取权限组中其他子权限。组内其他子权限可以直接使用。
- 现在,申请一个子权限,组内其他子权限不会自动获取。使用组内其他子权限的时候。需要再次申请。(但是这种情况不会弹出系统的权限申请框)如果不申请。会FC。
三.解决方案:
3.1 权限分组
同组权限一起申请。当我们申请权限时。申请同组的多个权限时,也只会弹出一次申请框。所以不如一起申请。
public class PermissionGroup {
......
//Storage权限
protected static String[] ABS_STORAGE = new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE
};
//Phone权限
protected static String[] ABS_PHONE = new String[] {
Manifest.permission.READ_PHONE_STATE, Manifest.permission.CALL_PHONE,
Manifest.permission.READ_CALL_LOG, Manifest.permission.WRITE_CALL_LOG,
Manifest.permission.USE_SIP, Manifest.permission.PROCESS_OUTGOING_CALLS
};
......
}
3.2 控制权限组粒度
因为机型问题,本以为可以定义好通用的PHONE权限,然后一起申请,可是这也依赖于App中Manifest列表里具体声明了哪些权限。假如我们仅仅在Manifest中声明了<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
权限。却要申请Phone组内的全部权限。有些机型会返回授权失败。所以控制粒度。
public class PermissionConstant extends PermissionGroup {
public static String[] PHONE;
public static String[] STORAGE;
static {
PHONE = new String[] {
Manifest.permission.READ_PHONE_STATE
};
STORAGE = ABS_STORAGE;
}
}
3.3 申请整个权限组。
所以当我们申请权限的时候,就直接申请整组权限吧。这样就会完美适配Android O了。
后续会用一个组件来解决这个问题。