问题背景
手机射频前端、天线会有很多MIPI器件,而这些MIPI器件前期需要调试,为了方便硬件工程师调参数,会在调试的软件版本内置一些工模APK让其使用。而这些工模APK需要软件相关人员根据需求进行代码编写,在实现新的需求时,楼主就遇到了一个上层APK调用JNI接口的问题,JNI层的接口调试OK,APK的代码开发了主要功能,还有一些功能没开发完,先将接口层的代码合入了库中。
CI流水线日构建的次日大版本刷测试机,使用需要调用JNI接口层代码的工模功能全部丧失,测试手机红屏报错。
问题分析
通过adb指令抓起android侧的log。
1 | adb logcat > temp.txt |
搜索了报错log打印的关键字,发现是新加的JNI层接口注册失败。提交接口代码前,还特意在APK层写了测试用例压测这个接口。
将之前开发的APK代码加入再进行测试,发现注册成功。初步怀疑是APK层没有调用这个接口导致。
开始在google上搜索是不是有想过的APK开发人员遇到过类似的问题,没有搜索到类似的案例。但是某个瞬间,想起自己在安卓官网有看到APK开发指南的一篇说明《缩减、混淆处理和优化您的应用》(其实楼主作为这方面开发的新人,问过一些工作七、八年开发较长时间的同事,是不太清楚这点的),猜测是上层没有调用JNI层的那个接口,导致java侧声明的JNI层的接口代码,在编译过程中删除了,通过APK反编译工具apktool(网上搜索下载),反编译已经编译出来的apk,发现在java代码中声明的那个接口代码被删除掉了。
也在项目级 build.gradle 文件中看到了这个开发打开了minifyEnabled这个开关:
1 | // Enables code shrinking, obfuscation, and optimization for only |
问题解决
将已经开发的APK调用这个接口的模块代码合入仓库,一起编译版本。
问题总结
下面安卓官网的文字,关于APK代码缩减的关键介绍,至于编译过程中实现代码缩减这项功能的源码具体实现,需要更多的APK编译想过的资料和代码查看,后续楼主会抽空多研究一些。
- 代码缩减(即摇树优化):从应用及其库依赖项中检测并安全地移除未使用的类、字段、方法和属性(这使其成为了一个对于规避 64k 引用限制非常有用的工具)。例如,如果您仅使用某个库依赖项的少数几个 API,缩减功能可以识别应用“未”使用的库代码并仅从应用中移除这部分代码。如需了解详情,请转到介绍如何缩减代码的部分。
- 资源缩减:从封装应用中移除不使用的资源,包括应用库依赖项中的不使用的资源。此功能可与代码缩减功能结合使用,这样一来,移除不使用的代码后,也可以安全地移除不再引用的所有资源。如需了解详情,请转到介绍如何缩减资源的部分。
- 混淆处理:缩短类和成员的名称,从而减小 DEX 文件的大小。如需了解详情,请转到介绍如何对代码进行混淆处理的部分。
- 优化:检查并重写代码,以进一步减小应用的 DEX 文件的大小。例如,如果 R8 检测到从未采用过给定
if/else语句的else {}分支,则会移除else {}分支的代码。如需了解详情,请转到介绍代码优化的部分。