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

相关推荐
wei_shuo1 天前
从数据中台到数据飞轮:实现数据驱动的升级之路
1024程序员节·数据飞轮
玖剹15 天前
矩阵区域和 --- 前缀和
数据结构·c++·算法·leetcode·矩阵·动态规划·1024程序员节
jamison_11 个月前
文心一言与 DeepSeek 的竞争分析:技术先发优势为何未能转化为市场主导地位?
人工智能·ai·chatgpt·gpt-3·1024程序员节
NaZiMeKiY1 个月前
HTML5前端第六章节
前端·html·html5·1024程序员节
jamison_12 个月前
颠覆未来:解锁ChatGPT衍生应用的无限可能(具体应用、功能、付费模式与使用情况)
ai·chatgpt·1024程序员节
NaZiMeKiY2 个月前
HTML5前端第七章节
1024程序员节
earthzhang20212 个月前
《Python深度学习》第四讲:计算机视觉中的深度学习
人工智能·python·深度学习·算法·计算机视觉·numpy·1024程序员节
明明真系叻2 个月前
2025.3.2机器学习笔记:PINN文献阅读
人工智能·笔记·深度学习·机器学习·1024程序员节·pinn
bitenum2 个月前
【C++/数据结构】队列
c语言·开发语言·数据结构·c++·青少年编程·visualstudio·1024程序员节
IT学长编程3 个月前
计算机毕业设计 基于SpringBoot的智慧社区管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·后端·毕业设计·课程设计·论文笔记·1024程序员节