目录

NDK 导致的包体积问题

​最近同事在升级 Andorid13 遇到了包体积变化的问题!

具体问题:分支 A 编译产出 APK 体积为 110M,而基于分支 A 修改代码,适配 了Android13 后,体积为 160M,足足差了 50M

他们似乎百思不得其解。

其实这种可复现的问题最好分析,只要将两个产物对比一下就好了。

当对比观察了两个 APK 以后,很明显的发现 so 体积有问题

当看到这里时,懂的都懂,那肯定是 strip 的问题了。使用 file 命令查看 so 以后,果然是 with debug-info, not stripped

那为什么会没有 strip 呢?

问题的表面原因

同事是本地打包编译,所以我当时让他使用 local.properties 配置 ndk.dir(在后续进一步分析中,发现这个方式其实已经废弃了,不过依然奏效),指定一个 ndk 路径,最终他打出的 APK 体积恢复到了 110M 左右

那已经实锤了,是 NDK 的问题

其实,在 android 打包过程中,有一个 Task 专门用于 strip so 的。后续,也在 log 中发现,如果 ndk 环境配置有问题,那一定会出现一些 strip 异常 log

于是,另一个同事,为了支持 CI 打包(因为升级 Android 13,同时升级 AGP,同时升级 JDK11),开始进行相应配置,最终在打包机上打出 APK !然而体积为惊人的 160M···

查看 jekins 环境(前端页面),发现 NDK 的环境变量是已经配置了的,这就很奇怪了!

于是,登上了打包机,echo 了一下 ANDROID_NDK,发现居然是空值!

十分兴奋的以为找到了原因,手动修改 ANDROID_NDK 环境变量,重新打包!

一个小时过去了,打出 APK 体积依然为惊人的 160M···

问题的深层原因

当时,在修改 ANDROID_NDK 环境变量时,就觉得不太对劲。

因为,这台机器编译正常分支是没有问题的,so 也被 strip 了,但是编译 Android13 这个分支却有问题。

如果是环境变量问题,那应该是全局问题。

这个时候,突然想到了另一个问题,AGP 是怎么知道 NDK 的路径的呢

一番搜索后发现,其实 AGP 版本升级后,有一些略为的差异,而 Android13 依赖于 AGP7.x,AGP7.x 依赖的默认 NDK 版本为 21.4.7075529

如果,你本地不存在对应的 NDK 版本,又没有指定 NDK 版本,当然 NDK 配置就失败了,但是编译过程中,如果源码没有 c/c++ 代码,并不会中端编译,只是没有把 so strip。

解决问题的标准方式

那已经知道了根本原因,解决起来也十分简单

  1. 如果你的工程中没有指定 NDK 版本,下载 AGP 默认支持的 NDK 版本即可!但是这种方式有一个问题:比如,同学A自己本地并不知道需要下载对应 NDK 版本,会导致他自己出包体积很大,但是 CI 打包体积很小,造成编译环境差异化的问题
  2. 标准解法,指定 NDK 版本。不要使用 local.properties,因为每个人的环境的 ndk 路径都不同,无法通用,且也无法提交到 git 仓库。强烈建议直接替换为 AGP 的 NDK DSL,可以直接在 build.gradle 中指定 ndk 版本,提交 git 仓库,所有人环境统一,只不过没有对应版本的同学,第一次可能有一个下载过程。