大连密封材料 发表于 2024-12-27 12:21:49

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Android13、14特别权限-应用安装权限适配