Android Apk 编译打包流程
2024-4-21
| 2024-9-2
0  |  Read Time 0 min
type
status
date
slug
summary
tags
category
icon
password
 
本文通过手动编译 apk 的形式,带你了解 Android apk 的生成流程。

Android Apk 编译打包流程

Android 项目从编译到打包流程如下(Google 官网已经找不到,取而代之是一张简化后的,但我还是更喜欢这张)
notion image
简要描述此流程使用的一些编译工具:
  • aapt:aapt(Android Asset Packaging Tool) 工具会打包应用中的资源文件,如 AndroidManifest.xml、layout 布局中的 xml 等,并将 xml 文件编译为二进制形式,当然 assets 文件夹中的文件不会被编译,图片及 raw 文件夹中的资源也会保持原来的形态,(需要注意的是 raw 文件夹中的资源也会生成资源 id。aapt 编译完成之后会生成 R.java 文件)。
  • aidl:AIDL 工具会将所有的 aidl 接口转化为 java 接口。
  • Java Compiler(Java编译器):当 AAPT 与 AIDL 工具将需要处理的数据处理好后,Java 编译器会将所有的java代码,包括R.java与 aidl 文件编译成 .class 文件。
  • dex:dex 工具会将上述产生的 .class 文件及第三库及其他 .class 文件编译成 .dex 文件(dex文件是Dalvik虚拟机可以执行的格式),dex文件最终会被打包进APK文件。
  • apkbuilder:apkbuilder 工具会将编译过的资源及未编译过的资源(如图片等)以及 .dex 文件打包成APK文件。
  • Jarsingner:生成 APK 文件后,需要对其签名才可安装到设备,平时测试时会使用 debug keystore,当正式发布应用时必须使用 release 版的 keystore 对应用进行签名。Jarsigner工具会根据相应的keystore生成相应的签名APK文件。
  • zipalign(release mode):zipalign 工具,它能够对打包的应用程序进行优化。在你的应用程序上运行 zipalign ,使得在运行时 Android 与应用程序间的交互更加有效率。

手动编译打包流程示例

本示例所使用电脑环境
  1. 准备一个 Android 项目,此项目只使用 Android-29 平台库,不做过多的依赖,文件结构如下
  1. 创建 build 文件夹,后面作为输出文件夹,使用 aapt2 编译工具,将 res 目录中的资源文件编译成一个名为 res.zip 的压缩包。
aapt2 compile -o build/res.zip --dir res命令解析
  • aapt2: 这是 Android Asset Packaging Tool 2 (aapt2) 的命令行工具,用于处理 Android 应用程序资源。
  • compile: 这是 aapt2 命令的子命令,指示 aapt2 编译资源文件。
  • -o build/res.zip: 这个参数指定编译后的资源文件输出的位置和文件名。在这里,资源文件将被编译成一个名为res.zip的压缩包,并存储在build目录下。
  • -dir res: 这个参数指定要编译的资源文件所在的目录。在这里,资源文件位于res目录下,aapt2 将编译这个目录中的资源文件。
  1. 对资源进行链接
aapt2 link build/res.zip -I $ANDROID_HOME/platforms/android-29/android.jar --java build --manifest AndroidManifest.xml -o build/app-debug.apk 命令解析
  • aapt2 link: 使用 aapt2 工具进行链接操作。
  • build/res.zip: 要链接的资源文件(通常是资源文件的压缩包)。
  • I $ANDROID_HOME/platforms/android-29/android.jar: 指定 Android 平台的 android.jar 文件,用于包含 Android 框架的类和资源。
  • -java build: 生成 R.java 文件到指定的目录 build 中,这个文件包含了资源 ID 的映射。
  • -manifest AndroidManifest.xml: 指定 AndroidManifest.xml 文件,这是 Android 应用程序的清单文件。
  • o build/app-debug.apk: 指定输出的 APK 文件路径和名称。
 
  1. 编译 .java 文件(把 R.java 文件迁移到 MainActivity.java 所在目录,请正确指定的类路径和源代码文件路径是正确的,以确保编译过程顺利进行)
javac -d build -cp $ANDROID_HOME/platforms/android-29/android.jar com/example/compile/old/*.java 命令解析
  • javac: Java 编译器命令。
  • d build: 指定编译后的 .class 文件输出目录为 build 目录。
  • cp $ANDROID_HOME/platforms/android-29/android.jar: 指定编译时的类路径,这里是指定了 Android 平台的 android.jar 文件,以便编译器能够找到 Android 平台的类和接口。
  • com/example/compile/old/*.java: 要编译的 Java 源代码文件,这里指定了一个包路径下的所有 Java 文件进行编译。
编译后目录结构如下
  1. 生成 Dex 文件
d8 --output build/ --lib $ANDROID_HOME/platforms/android-29/android.jar build/com/example/compile/old/*.class 命令解析
  • d8: 这是一个命令行工具,用于将 Java 字节码文件转换为 Dex 格式,以便在 Android 设备上运行。
  • -output build/: 这个选项指定了输出目录为 build/,即将转换后的 Dex 文件输出到该目录。
  • -lib $ANDROID_HOME/platforms/android-29/android.jar: 这个选项指定了 Android 平台库的路径,其中 $ANDROID_HOME 是 Android SDK 的根目录,android-29 是 Android API 版本,android.jar 是 Android 平台库文件。
  • build/com/example/compile/old/*.class: 这是要转换的 Java 字节码文件的路径,通配符 .class 表示选择该目录下所有的 .class 文件。
编译后目录结构如下
  1. 将 dex 文件放入 apk 文件中
zip -j build/app-debug.apk build/classes.dex 参数解析
  • zip: 这是用于创建和修改zip文件的命令。
  • j: 这个选项表示在压缩文件时不包含目录路径,只压缩文件本身。
  • build/app-debug.apk: 这是指定要创建的zip文件的路径和名称。在这里,将创建一个名为 app-debug.apk 的zip文件,并存储在 build 目录下。
  • build/classes.dex: 这是指定要添加到zip文件中的文件路径和名称。在这里,classes.dex 文件将被添加到 app-debug.apk 中。
  1. 签名,使用 debug 签名 密码 “android”
apksigner sign -ks ~/.android/debug.keystore build/app-debug.apk 参数解析
  • apksigner: 这是用于对 APK 进行签名的工具。
  • sign: 这是 apksigner 的子命令,指示对 APK 文件进行签名操作。
  • ks ~/.android/debug.keystore: 这个参数指定了用于签名 APK 的密钥库文件的路径。在这里,~/.android/debug.keystore 是密钥库文件的路径。
  • build/app-debug.apk: 这是指定要签名的 APK 文件的路径和名称。在这里,app-debug.apk 将被签名。
  1. 将最终 .apk 文件安装到模拟器或真机
notion image
 
 
 
通过这个示例可以看出,即使在小型项目中,编译和打包 Android 应用程序也需要耗费相当的精力。而在大型项目中,涉及数百甚至数千个资源文件、Java/Kotlin 文件,以及各种测试、Lint 检测、编译(apt、asm 等工具又会干预编译)、链接和优化等流程。此外,还要考虑到模块化、复杂的依赖关系等因素,手动编译这样的项目几乎是不可能的任务,并且手动编译容易出错、效率低下。
因此,构建工具如 Gradle 应运而生。Gradle 等构建工具能够自动化和简化整个构建流程,从而减轻开发人员的负担,并确保构建过程的可靠性和一致性。
简洁优雅如 Gradle,也不要高兴的太早,掉入 Gradle 的坑里又是另外一个故事啦。

参考文档&资料

 
 
 
当我在写技术博客时我在思考什么Android Gradle Plugin 编译流程
  • Utterance
Catalog