首页 > 其他分享 >Android Dangerous权限的处理【设为默认】

Android Dangerous权限的处理【设为默认】

时间:2023-02-23 01:11:07浏览次数:47  
标签:requestedPermissions Dangerous 默认 int Android 权限 permissions pm

Android Dangerous权限的处理【设为默认】

在日常的使用中,如果我们调用到某一个接口,该接口依赖于危险权限的声明,平时我们会去对权限进行检查,检查这个权限是否被赋予,如果没有被赋予,就需要进行动态申请,否则会报权限异常的Exception.

但如果我本人比较懒,不想手动动他,权限就给他算了。针对和由系统集成的apk而言,可以考虑两种方式。

android:sharedUserId = "android.uid.system" 加上这个后,对应的应用瞬间变得niubility,一般apk是运行在普通的user用户下,加上该标签后,就会运行在system用户下,同时系统级用户对于危险权限是默认授予的,同时用户无法进行操作的。

除了上面这种niubility方法,还有一种方法也可以让某个应用默认授予权限并且用户无法操作,这也是本次要将的重点,稍微结合源码来介绍下

接下来进行操作的实现:
1.创建对应的配置文件,别问,问就是有人要读
2.编写对应的集成文档,别问,问就是有人要从那里取

先说一下1吧,这里简单给个例子:
加入我们要继承的配置文件是 default_permission_xxx.xml

<?xml version="1.0" encoding="utf-8"?>
<exceptions>
  
  <!-- exception package 为要授予权限的app包名 -->
  <!-- permission name 为要授予权限的app默认授予的权限 -->
  <!-- permission的fixed表示授权后是否可以被非系统组件修改权限 -->
  <exception package="com.android.xxxtest">
      <permission name="android.permission.巴拉巴拉" fixed="false"/>
  
  </exception>
  
</exceptions>

这里简单说一下,首先package是要设置对应权限的包名,接着在权限中的name是要设置为默认授予的权限名称(这里针对dangerous权限而言,priv权限有自己的定义方式),最后的fixed标志位是用来设置是否可以被非系统组件修改的标志,从用户体验的角度来看就是用户能不能修改该权限。

这里要读的内容差不多按照这个格式来写,那该给它放到哪去呢?
接着就要想办法把这个配置文件集成到特定的位置去。

这里以bp文档为例,mk可以看参考文档中,写法都大差不大:

android_app {
    name : "balabala",
    ...

    required:["permission_balabala"],

}

prebuilt_etc {
    name: "permission_balabala",
    product_specific: true,
    sub_dir: "default-permissions",
    src: "default-permissions-xxxx.xml",
}

简单说明下:
对于android_app的name,就是我们应用的名,
required中包含了要继承的配置文件,
prebuilt_etc 是指要往某个etc/的路径下集成,
product_specific是指往product分区进行集成,除此之外还有vendor,system_ext,system,Oem等
sub_dir是指在对应的分区/etc/的子路径下,这里要是集成危险权限,所以必须是default-permissions的文件名,敲重点
最后的src就是对应的资源文件

这两步配置好了就能够实现对应应用的默认权限授予的配置。

接着简单看点源码:
DefaultPermissionGrantPolicy.java
看这个类名应该就直到是专门负责默认权限授予工作的。主要是pms来进行调用

public void grantDefaultPermissions(int userId) {
    DelayingPackageManagerCache pm = new DelayingPackageManagerCache();

    grantPermissionsToSysComponentsAndPrivApps(pm, userId);
    grantDefaultSystemHandlerPermissions(pm, userId);
    grantDefaultPermissionExceptions(pm, userId);

    // Apply delayed state
    pm.apply();
}

看一下中间的三巨头方法,第一个应该是授予默认的系统权限和priv权限
第二个是赋予一些系统级应用的默认权限,比如说语音助手,电话等等
第三个就是今天的重头戏,授予用户配置的危险权限

private void grantDefaultPermissionExceptions(PackageManagerWrapper pm, int userId) {
    mHandler.removeMessages(MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS);

    synchronized (mLock) {
        // readDefaultPermissionExceptionsLocked 这个方法会去对根目录,vendor,Odm,product,以及system_ext分区下etc/default-permissions/下的xml进行读取,读取后返回给mGrantExceptions
        if (mGrantExceptions == null) {
            mGrantExceptions = readDefaultPermissionExceptionsLocked(pm);
        }
    }

    Set<String> permissions = null;
    final int exceptionCount = mGrantExceptions.size();
    for (int i = 0; i < exceptionCount; i++) {
        String packageName = mGrantExceptions.keyAt(i);
        PackageInfo pkg = pm.getSystemPackageInfo(packageName);
        List<DefaultPermissionGrant> permissionGrants = mGrantExceptions.valueAt(i);
        final int permissionGrantCount = permissionGrants.size();
        for (int j = 0; j < permissionGrantCount; j++) {
            DefaultPermissionGrant permissionGrant = permissionGrants.get(j);
            if (!pm.isPermissionDangerous(permissionGrant.name)) {
                Log.w(TAG, "Ignoring permission " + permissionGrant.name
                        + " which isn't dangerous");
                continue;
            }
            if (permissions == null) {
                permissions = new ArraySet<>();
            } else {
                permissions.clear();
            }
            permissions.add(permissionGrant.name);

            // 注意看! 这个标志叫permissionGrant.fixed
            grantRuntimePermissions(pm, pkg, permissions, permissionGrant.fixed,
                    permissionGrant.whitelisted, true /*whitelistRestrictedPermissions*/,
                    userId);
        }
    }
}
private void grantRuntimePermissions(PackageManagerWrapper pm, PackageInfo pkg,
            Set<String> permissionsWithoutSplits, boolean systemFixed, boolean ignoreSystemPackage,
            boolean whitelistRestrictedPermissions, int userId) {
    UserHandle user = UserHandle.of(userId);
    if (pkg == null) {
        return;
    }

    String[] requestedPermissions = pkg.requestedPermissions;
    if (ArrayUtils.isEmpty(requestedPermissions)) {
        return;
    }

    // Intersect the requestedPermissions for a factory image with that of its current update
    // in case the latter one removed a <uses-permission>
    String[] requestedByNonSystemPackage = pm.getPackageInfo(pkg.packageName)
            .requestedPermissions;
    int size = requestedPermissions.length;
    for (int i = 0; i < size; i++) {
        if (!ArrayUtils.contains(requestedByNonSystemPackage, requestedPermissions[i])) {
            requestedPermissions[i] = null;
        }
    }
    requestedPermissions = ArrayUtils.filterNotNull(requestedPermissions, String[]::new);

    final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
    ApplicationInfo applicationInfo = pkg.applicationInfo;

    int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
    // 这个值就是在配置文件中的fixed标志位的值,如果是true,就把对应的权限标志位添加上PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
    if (systemFixed) {
        newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
    }
}

给上一个加上该标志位后的示例dumpsys结果:

User 13:
    ......
      runtime permissions:
        android.permission.BLUETOOTH_CONNECT: granted=true, flags=[ SYSTEM_FIXED|GRANTED_BY_DEFAULT|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]

可以看到,对应的runtime权限的列表中,flags包含了SYSTEM_FIXED标签并且有GRANTED_BY_DEFAULT标签,说明该权限是默认授予,并且用户无法进行操作的。具体如何让其不进行操作,可以看Setting对于system_fixed的标志位的处理,会有一个disable的过程。

参考文档:
https://blog.csdn.net/qq_34250794/article/details/128284337
https://blog.csdn.net/qq_37580586/article/details/120132638

标签:requestedPermissions,Dangerous,默认,int,Android,权限,permissions,pm
From: https://www.cnblogs.com/zhenji-li/p/17146537.html

相关文章

  • Android笔记-跳转到相册选择图片
    跳转到相册选择图片即设置一个点击事件,点击之后即可跳转到相册进行图片的选择具体的实现步骤:界面很简单的啦,这里就直接将源代码放出来啦:<?xmlversion="1.0"encoding=......
  • Android学习——控件TextView
    1.基本2.带阴影的3.跑马灯效果......
  • 关于首次接触Android Studio
    今天正式接触了AndroidStudio,刚开始学,创建一个安卓工程这个东西  下载太慢。      此时千万不能断网,不然一切都会重新开始。 ......
  • Android 启动优化(二) - 有向无环图的原理以及解题思路
    Android启动优化(一)-有向无环图Android启动优化(二)-拓扑排序的原理以及解题思路Android启动优化(三)-AnchorTask使用说明Android启动优化(四)-手把手教你实现An......
  • 【Android】“你好,世界”的地基
    哪一个活动?创建一个普通的BaseActivity类,并将其定为所有活动类的父类。publicclassBaseActivityextendsAppCompatActivity{@OverrideprotectedvoidonC......
  • Android Studio获取MD5、SHA1
    很多的时候都需要获取Android的MD5、SHA1值,像高德、百度地图就是例子需要这个值做密钥。下面Androidstudio工具获取方法1、点击studio面板右上角Gradle,找到app>Tas......
  • Android Studio第一个程序的开发
    1:首先创建一个device,创建成功后运行,就会显示text的内容,为了修饰,打开code,编写代码修改手机app,遇到一个问题就是在xml编写android:background="#f00">无效,在TextView中修改t......
  • Android studio模拟器设置悬浮
    File->Settings->Tools->Emulator,如图这里不要勾选,重启,点击三角形运行项目,弹出来了  ......
  • Android预览超长图原图并且可以滑动查看超长图
    概述:根据需求方的要求,app中预览大图需要显示高清图片。且支持高清预览横向长图(原图)和纵向长图(原图)。且图片可以自由的放大缩小,并且超长图默认需要撑满横屏或者竖屏,可以......
  • Android中drawable和mipmap到底有什么区别
    欢迎通过我的个人博客来查看此文章老项目代码中发现有的图片放到了drawable中,有的图片放到了mipmap中,开发时秉承哪个目录下文件多放哪里的原则,偶尔有疑惑搜一搜文......