先上图,看看最终我们可以得到什么样子的结果:
截图来自 android开发工具箱, 点我下载 android开发工具箱
应用内权限信息分为两个部分,我们先来看应用内权限使用情况。
PackageManager pm = context.getPackageManager();
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
if (packageInfo.requestedPermissions != null) {
for (String permission : packageInfo.requestedPermissions) {
PermissionInfo permissionInfo = pm.getPermissionInfo(permission, 0);
if ((permissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0
|| (permissionInfo.flags & FLAG_REMOVED) != 0) {
continue;
}
boolean isHasPermission = PackageManager.PERMISSION_GRANTED == pm.checkPermission(permission, packageName);
...
}
}
获取权限列表步骤大致为:
1. 先从PackageInfo获取应用内使用权限的列表,得到一个String数组
2. 遍历数组,使用PackageManager获取PermissionInfo对象
3. 根据permissionInfo.flags对结果进行筛选
4. 判断应用是否已经获得了此权限
这样,我们的列表所需的数据就齐了。下面我们看看PermissionInfo里面都有些什么我们需要的信息
public class PermissionInfo extends PackageItemInfo implements Parcelable {
public int protectionLevel;
public @Nullable String group;
public @Flags int flags;
//获取权限描述信息
public @Nullable CharSequence loadDescription(@NonNull PackageManager pm) {
...
}
}
我们使用上面的信息即可获取权限的level、group、权限的描述。flags是之前我们用到的属性。
系统没有提供给我们把int类型的protectionLevel转换成String的方法,但是,PermissionInfo类中有个隐藏的方法:
/** @hide */
@UnsupportedAppUsage
public static @NonNull String protectionToString(int level) {
String protLevel = "????";
switch (level & PROTECTION_MASK_BASE) {
case PermissionInfo.PROTECTION_DANGEROUS:
protLevel = "dangerous";
break;
case PermissionInfo.PROTECTION_NORMAL:
protLevel = "normal";
break;
case PermissionInfo.PROTECTION_SIGNATURE:
protLevel = "signature";
break;
case PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM:
protLevel = "signatureOrSystem";
break;
}
...
}
这里不但隐藏了,还加了UnsupportedAppUsage注解,所以只能复制出来一份了。同时,这段代码也给出了判断一个权限是否是危险权限的方法:
public static boolean isDangerous(int level) {
return (level & PermissionInfo.PROTECTION_MASK_BASE) == PermissionInfo.PROTECTION_DANGEROUS;
}
系统没有直接提供获取权限描述的属性,但是提供了方法loadDescription,最后来看一下group。
group的概念是android6引入运行时权限引入了,但是到了android10,应用无法在界面中查询权限的分组方式。所以我们在不同版本上获取group信息会有所不同。
下面以`android.permission.ACCESS_FINE_LOCATION`权限为例。
在android6-9上面,我们获取到的group内容为:
android.permission-group.LOCATION
在android10上面获取到的group内容为:
> android.permission-group.UNDEFINED
综上,显示应用内使用的权限的几个关键信息:权限名称、级别、分组以及权限描述就都有了。
自定义权限要要更简单一点
if (packageInfo.permissions != null) {
for (PermissionInfo permissionInfo : packageInfo.permissions) {
boolean isHasPermission = PackageManager.PERMISSION_GRANTED == pm.checkPermission(permissionInfo.name, packageName);
...
}
}
packageInfo.permissions是PermissionInfo数组,所以少了使用PackageManager获取PermissionInfo对象这一步,其余逻辑与展示系统权限逻辑完全一致,至此,我们就能制作一个展示应用内权限的页面了。