Android 手工打包:用 aapt2 + d8 走一遍 APK 链路,构建出错才有处可查
Android 手工打包:用 aapt2 + d8 走一遍 APK 链路,构建出错才有处可查
用 Gradle 打包 Android 应用很方便,但一旦构建失败,报错往往藏在插件和缓存后面,很难定位。把链路拆开手工走一遍——aapt2 编译资源、javac 编译代码、d8 转 dex、zipalign 对齐、apksigner 签名——每一步的产物都看得见,出问题就知道卡在哪一环。这条链路也适合离线环境:不需要下载依赖,只要本机有 SDK 工具即可。
第一步:aapt2 编译资源,生成 R.java
先把 AndroidManifest.xml、res/ 下的布局和字符串交给 aapt2 link,生成带资源的 APK 雏形和 R.java。资源引用写错、Manifest 里 activity 没声明,这一步就会直接报错,而不是拖到安装时才暴露。
aapt2 link -o app-unaligned.apk \
--manifest AndroidManifest.xml \
-I $ANDROID_HOME/platforms/android-34/android.jar \
-R res/layout/*.xml -R res/values/*.xml \
--java gen/
注意 --java gen/ 生成的 R.java 要放进后续 javac 的源码路径,否则 Java 代码里引用的 R.layout.main 编译不过。
第二步:javac 与 d8,代码变成 dex
用 javac 把业务代码连同 R.java 一起编译成 class 文件,再用 d8 转成 classes.dex。d8 的输入是 class 文件夹,输出直接进 APK:
javac -cp $ANDROID_HOME/platforms/android-34/android.jar \
-d classes/ src/com/example/app/*.java gen/com/example/app/R.java
d8 --output dex/ classes/
如果这里报方法数超限或类重复,问题在依赖和代码本身,与资源无关——分步的好处就在这里:报错的步骤就是出问题的环节。
第三步:组装、对齐、签名,缺一不可
把 dex、资源 APK、assets 里的静态文件合并成一个 APK,再依次做 zipalign 对齐和 apksigner 签名。顺序不能乱:先对齐后签名,签名后再改动文件会破坏签名校验。
zipalign -f 4 app-unaligned.apk app-aligned.apk
apksigner sign --ks debug.keystore --ks-pass pass:android \
--out app.apk app-aligned.apk
apksigner verify app.apk
最后用 apksigner verify 和 aapt2 dump badging 各验一次:前者确认签名有效,后者确认包名、版本号和启动 Activity 都如预期。手工链路不追求快,它追求的是每一步都可验证——当 Gradle 报错看不懂时,回到这条链路,往往一眼就能看到真正的原因。
排障:先看步骤,再看报错原文
手工链路还有一个附带好处:排障时不用猜。资源编译失败,先查布局里引用的字符串和图片名是否存在,拼写错一个字母就会在这里暴露;javac 失败,先看 R.java 是否生成、源码路径是否把 gen 目录加进去;安装时提示签名冲突,往往是旧包用了不同的 debug keystore,卸载旧包重装即可,不要急着改包名绕过去。每一类报错都对应一个步骤,定位时间自然就短了。
签名与版本:debug 能用,不等于能上架
手工打包时常用 debug keystore 做验证,但它只适合本机测试:正式发布必须用自己保管的 release keystore,一旦丢失就无法再更新同一包名的应用。同时记得在 Manifest 里维护好 versionCode 与 versionName——versionCode 每次发布必须递增,否则应用商店和设备都会拒绝覆盖安装。把“对齐、签名、验签、查 badging”写成固定收尾四步,手工包也能达到和 Gradle 产物一样的交付标准。
- 点赞
- 收藏
- 关注作者
评论(0)