Android13、14特殊权限-应用安装权限适配

Android13、14特殊权限-应用安装权限适配

文章目录

一、前言

Android13、14 的源码发现一个问题系统签名应用声明了应用安装权限,

但是安装应用的时候还是没有安装应用权限,

需要在原生Settings中的特殊权限设置一次权限打开才有安装应用权限。

本文只介绍解决方法,里面framework的代码是实际项目的修改中拿来的,不是我自己研究的,不做过多分析。

二、权限适配

AndroidManifest.xml 声明权限:

复制代码
 <!-- Android O(8) needs this permission to install apk -->
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

Android13:

复制代码
@UnsupportedAppUsage
private static String[] sOpPerms = new String[] {
        android.Manifest.permission.ACCESS_COARSE_LOCATION,
        android.Manifest.permission.ACCESS_FINE_LOCATION,
        ...
        AppOpsManager.MODE_ALLOWED, // READ_PHONE_NUMBERS
-        AppOpsManager.MODE_DEFAULT, // REQUEST_INSTALL_PACKAGES
+        AppOpsManager.MODE_ALLOWED, // REQUEST_INSTALL_PACKAGES
        AppOpsManager.MODE_ALLOWED, // PICTURE_IN_PICTURE
        AppOpsManager.MODE_DEFAULT, // INSTANT_APP_START_FOREGROUND
        ...
}

可以看到安装应用权限默认不是 MODE_ALLOWED允许状态,设置成允许状态就行。

Android14:

复制代码
static final AppOpInfo[] sAppOpInfos = new AppOpInfo[]{
    ...
    new AppOpInfo.Builder(OP_READ_PHONE_NUMBERS, OPSTR_READ_PHONE_NUMBERS, "READ_PHONE_NUMBERS")
        .setPermission(Manifest.permission.READ_PHONE_NUMBERS)
        .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
    new AppOpInfo.Builder(OP_REQUEST_INSTALL_PACKAGES, OPSTR_REQUEST_INSTALL_PACKAGES,
            "REQUEST_INSTALL_PACKAGES").setSwitchCode(OP_REQUEST_INSTALL_PACKAGES)
    -    .setPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES).build(),
    +    .setPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES)
    +    .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
    ...


}

Android14 把app权限信息封装成AppOpInfo对象了。

从上面代码可以看到安装应用的权限未设置默认模式,添加默认许可即可。

这里的默认许可,也不是所有应用都需要,

而是拥有了安装应用这个特殊权限的应用才默认许可安装应用。

第二种方法

复制代码
    private void initOpsPermission(Context context) {
 
        try {
            setPackageAppOpsPermission(context, "com.android.bluetooth", AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW);
            setPackageAppOpsPermission(context, "com.skg.filemanager", AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES);
        } catch (Exception e) {
            e.printStackTrace();
            DebugLog.debug("error = " + e.getMessage());
        }

    }

    //设置特殊权限通过
    private void setPackageAppOpsPermission(Context context, String packageName, String opsString) {

        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        PackageManager manager = context.getPackageManager();
        int uid = 1;
        try {
            ApplicationInfo packageInfo = manager.getApplicationInfo(packageName, 0);
            uid = packageInfo.uid;
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        DebugLog.debug("uid = " + uid);
        mAppOps.setUidMode(opsString, uid, AppOpsManager.MODE_ALLOWED);
    }

值得注意的是系统签名应用uid=1000的应用,可以设置打开特殊权限,不能关闭特殊权限,

否则应用会崩溃报错,原生设置中关闭签名应用的特殊权限也是会异常崩溃的。

之前看代码,特殊权限好像是根据uid相关的,

如果关闭这个权限,其他使用这个权限的系统签名应用就会有异常。

三、其他

1、特殊权限-应用安装权限适配小结

有两种方式适配修改:

复制代码
第一种是在framework中设置默认许可。
第二种是在系统代码中设置给与权限。

2、dumpsys package查看获取到了应用安装权限

复制代码
console:/ #dumpsys package com.debug.filemanager | grep -i install
    installerPackageName=null
    installerPackageUid=-1
    installPermissionsFixed=false
      android.permission.REQUEST_INSTALL_PACKAGES //请求的权限
 
    User 0: ceDataInode=1876 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
      installReason=0
      firstInstallTime=2024-10-21 21:21:37
      uninstallReason=0
    install permissions:
      android.permission.INSTALL_LOCATION_PROVIDER: granted=true
      android.permission.READ_INSTALLED_SESSION_PATHS: granted=true
      android.permission.INSTALL_DYNAMIC_SYSTEM: granted=true
      com.android.certinstaller.INSTALL_AS_USER: granted=true
      android.permission.REQUEST_INSTALL_PACKAGES: granted=true  //显示获取到了安装应用的权限
console:/ # 

但是从代码或判断是否获取到安装应用权限是未获取到权限的。

复制代码
boolean hasInstallPermission = context.getPackageManager().canRequestPackageInstalls();
LogUtil.debug("hasInstallPermission = " + hasInstallPermission);

打印返回是false的。

如果要知道为啥返回的false,就要研究获取权限的流程了。

有兴趣的可以自己看看。

3、Android权限系统:应用操作管理类AppOpsManager(Android 10)

AppOpsManager 是Google在Android4.3里面引进的应用程序操作(权限)的管理类,核心实现类为AppOpsService。

Google对AppOpsManager的说明在:

AppOpsManager

  app op(应用操作)的出现比运行时权限早,最初在没有出现运行时权限的时候,

  应用一旦被安装成功,是会被一次性授予所有需要的权限的,

  所以限制应用权限的唯一方案是使用AppOpsManager。

  但在现在,app op不但覆盖了所有的运行时权限(例如,拍照的app op是OP_CAMERA,

  也有对应的运行时权限Manifest.permission.CAMERA),还添加了一些没有对应运行时权限的操作(例如,读剪贴板的app op是OP_READ_CLIPBOARD,却没有对应的运行时权限)。

  此外,AppOpsManager提供了跟踪记录的功能,以方便开发者了解系统敏感操作的访问记录,

  使用noteOp(String, int, String)/startOp(String, int, String)可以让系统执行记录,

  而使用unsafeCheckOp(String, int, String),系统不会执行记录。

  noteOp/startOp/unsafeCheckOp在记录敏感操作信息的同时,

  还有一个返回值,开发者可以根据这个返回值决定下一步操作。

  

  返回值有:

复制代码
  1.MODE_ALLOWED:访问者可以访问该敏感操作;
  2.MODE_IGNORED:访问者不可以访问该敏感操作,但是不会引发crash;
  3.MODE_ERRORED:访问者不可以访问该敏感操作,会引发crash;
  4.MODE_DEFAULT:访问者来决定访问该敏感操作的准入规则。

详细介绍:

https://blog.csdn.net/Invoker123/article/details/109176511

4、Android13 授予特殊应用权限代码

Android 权限类别有啥,网上很多是说有普通权限和危险权限,其实是不准确的。

Android 权限分为普通权限,动态权限,特殊权限,私有权限。

https://blog.csdn.net/wenzhi20102321/article/details/143082504

相关推荐
fangzhanpeng1683 天前
快速掌握C#语言基础知识点(1.基础数据类型)
开发语言·c#·1024程序员节
无己心5 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u01030552711 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u01030552712 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝13 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u01030552713 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552714 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u01030552716 天前
Java实用类应用精讲
人工智能·1024程序员节
u01030552716 天前
Java I/O核心操作实战
人工智能·1024程序员节
u01030552717 天前
ArrayList操作详解与实战应用
人工智能·1024程序员节