rany 发表于 2017-7-14 16:53:02

Android 7实现具体权限管理思路

本帖最后由 rany 于 2017-7-14 16:53 编辑

原生Android N中有自带的权限管理功能,在“设置->应用->应用信息->权限"中,这是简化的设置,只能对每个应用进行权限组的管理,一些特殊的权限也没有进行统一的管理。国内的很多ROM实现了对各个具体权限的管理,如MIUI。这里我简单的说明一下对具体权限管理的思路。
首先,要实现对具体权限管理要先了解Android系统对权限的定义。Android系统把权限分为了权限(Permission)和权限组(Permission Group)两部分。权限可以归类到一个具体的权限组中,有一些权限没有属于特定的组。具体权限的定义可以参考Google官方定义的文档(国内可访问):https://developer.android.google.cn/reference/android/Manifest.permission.html权限组的定义:https://developer.android.google.cn/reference/android/Manifest.permission_group.html
其中部分权限与权限组的关联可参考:https://developer.android.google.cn/guide/topics/permissions/requesting.html 原生Android 7中管理的就是权限组。通过这些定义可以生成或定制自己想要管理的权限列表。

然后是要知道如何获取申请这个权限的所有App。在Android系统源码中有获取申请这个权限组下的权限所有App的实现源码,在packages/apps/PackageInstaller/包中,可以根据此源码实现获取每个权限的所有申请App。以下代码为我的修改实现:
UserManager userManager = mContext.getSystemService(UserManager.class);
for (UserHandle user : userManager.getUserProfiles()) {
    List<PackageInfo> apps = mContext.getPackageManager()
            .getInstalledPackagesAsUser(PackageManager.GET_PERMISSIONS,
                  user.getIdentifier());
    final int N = apps.size();
    for (int i = 0; i < N; i++) {
      PackageInfo app = apps.get(i);
      if (app.requestedPermissions == null) {
            continue;
      }
      // 遍历APP权限
      for (int j = 0; j < app.requestedPermissions.length; j++) {
            String requestedPerm = app.requestedPermissions;
            // 判断APP是否申请当前权限
            if (requestedPerm.equals(mPermissionName)) {
                mPermissionApps.add(new PermissionApp(
                        app.packageName,
                        app.applicationInfo.loadLabel(mPm),
                        app.applicationInfo.loadIcon(mPm),
                        app.requestedPermissionsFlags));
                break;
            }      
      }
    }
}
PermissionApp的定义如下:

public static final class PermissionApp {
      public String packageName;
      // APP显示名称
      public CharSequence label;
      public Drawable icon;
      // 记录APP授权状态
      public int mode;

      public PermissionApp(String packageName, CharSequence label, Drawable icon, int mode) {
            this.packageName = packageName;
            this.label = label;
            this.icon = icon;
            this.mode = mode;
      }
    }
在权限管理中,重要的操作就是判断APP是否已经被授予权限,如果只是简单的判断的话可以通过
// PermissionApp pa;
(pa.mode & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0进行的判断。然而对于Android 6.0后的运行时申请的权限,我们一般要多一个可以设置的选项 提示,而不只是允许与禁止。Android中跟运行时申请的权限相关的两个java类为AppOpsManager和AppOpsService,在Android源码的frameworks/base/core/java/android/app中。AppOpsManager中定义了checkOp、checkOpNoThrow、noteOp和noteOpNoThrow等权限验证方法。同时PackageInfo类中的requestedPermissionsFlags也记录了App相应的权限的状态。
最后就是权限的设置了。权限的设置可使用AppOpsManager的setUidMode和PackageManger的updatePermissionFlags结合设置。可以参考packages/apps/PackageInstaller中的com.android.packageinstaller.permission.model.AppPermissionGroup类的实现。



牛头 发表于 2017-8-5 17:15:46

挺实用的,感谢分享
页: [1]
查看完整版本: Android 7实现具体权限管理思路