Class 分析插件助力 Android 13 适配落地

Class 分析插件助力 Android 13 适配落地

Android 13 发布马上有 3 个月了,各厂都现已开端了适配工作,我司也不破例。但适配前有一个问题需求处理,如果衡量这次适配的工作量,怎么计算哪些模块需求改造,并能精确的找到对应模块负责人。

传统办法也有,经过 as 的 Find Usages 功用,找到该办法有被哪些类引证。例如 Android13 适配中,使用动态注册的播送接收器有必要以明显的办法指出是否答应其他使用拜访,所以,咱们有必要找到是哪些模块在调用 registerReceiver 办法,咱们需求针对这些办法进行适配,如下是经过 Find Usages 检查的成果:

Class 分析插件助力 Android 13 适配落地

然后再手动计算下是哪些模块在调用,并记载起来,然后持续下个适配的检测,终究评估出改造的工作量。显然,传统办法也不是不能做,仅仅有点费劲罢了。

说来也怪,Google 致力推广每个版别的发布,却没有提供一个工具来辅佐开发者去完成自动化检查,也是够糟糕的。

其实想想也不难,咱们的诉求不就是想找到需求适配的办法是在哪个模块被哪个类引证了嘛,咱们能够来思考下,如果要完成自动化的话,咱们需求做哪些工作:

  1. 预备好一个配置文件,描绘咱们需求检测的适配办法
  2. 找到使用的一切依靠,并提取出依靠中的 class.jar
  3. 解析 class.jar,提取出 class 文件并对其进行剖析
  4. 剖析 class 文件中有无调用到配置文件中的适配办法
  5. 如果有,则记载这个依靠,并记载这个 class 文件
  6. 终究,将收集到的成果输出成一个文件

比方,咱们想适配 Android 13 如下几个 case:

  • 后台的传感器权限适配:App 在后台运行时,如果需求获取心率、体温、血氧饱和度等传感器信息,关于声明了 BODY_SENSORS 权限还有必要声明新的 BODY_SENSORS_BACKGROUND 权限。
  • 更安全的系统组件适配:使用动态调用 registerReceiver 注册播送接收器有必要以明显的办法指出是否答应其他使用拜访,即其他使用是否能够向其发送播送。否则,在动态注册时系统将抛出安全异常。
  • 受限的 non-SDK 接口:不答应调用 ActivityThread.mCurDefaultDisplayDpi 字段

那么,咱们的配置文件能够这么去描绘:

{
  "stringRef": [
    "android.permission.BODY_SENSORS"
  ], 
  "methodRef": [
    {
      "className": "android/content/Context",
      "method": "registerReceiver"
    }
  ],
 "fieldRef": [
    {
      "className": "android/app/ActivityThread",
      "fieldName": "mCurDefaultDisplayDpi",
      "signature": "I"
    }
  ],
}
  • stringRef : 描绘字符常量的调用的状况。例如,咱们需求检查一切依靠中,有哪些模块在调用 android.permission.BODY_SENSORS 权限
  • fieldRef : 描绘字段的调用状况。例如,咱们需求检查一切依靠中,有哪些模块在调用 ActivityThread.mCurDefaultDisplayDpi 字段
  • methodRef : 描绘办法的调用状况。例如,咱们需求检查一切依靠中,有哪些模块在调用 Context.registerReceiver 办法

终究的输出成果文件如下:

{
  "stringRef": [
    {
      "name": "android.permission.BODY_SENSORS",
      "ref": [
        {
          "dependencies": "\u0027:android-lib2:debugApiElements\u0027",
          "className": "com/codelang/android_lib2/TestCase"
        }
      ]
    }]
    }
  ],
  "methodRef": [
    {
      "className": "android/content/Context",
      "method": "registerReceiver",
      "ref": [
        {
          "dependencies": "\u0027:android-lib2:debugApiElements\u0027",
          "className": "com/codelang/android_lib2/TestCase"
        },
        {
          "dependencies": "androidx.appcompat:appcompat:1.4.2",
          "className": "androidx/appcompat/app/AppCompatDelegateImpl$AutoNightModeManager"
        }
      ]
    }
  ],
  "fieldRef": [
    {
      "className": "android/app/ActivityThread",
      "fieldName": "mCurDefaultDisplayDpi",
      "signature": "I",
      "ref": [
        {
          "dependencies": "\u0027:android-lib2:debugApiElements\u0027",
          "className": "com/codelang/android_lib2/TestCase"
        }
      ]
    }
  ]
}
  • stringRef 中剖析出 android-lib2 模块中的 TestCase 类调用了 BODY_SENSORS 权限
  • methodRef 中剖析出 android-lib2 模块中的 TestCase 类调用了 Context.registerReceiver 办法
  • fieldRef 中剖析出 android-lib2 模块中的 TestCase 类调用了 ActivityThread.mCurDefaultDisplayDpi 字段

终究的接入与使用状况,能够参阅 Github 的 README.md,目前插件已开源,项目源码可检查 github.com/MRwangqi/pl…