相信每一位Android开发者都对 APK (Android Package) 文件再熟悉不过了,我们开发的应用最终都要打包成 APK 才能安装到设备上运行。但是,从我们编写的代码和资源,到最终生成可安装的 APK,这中间到底经历了哪些步骤? Android Gradle Plugin (AGP) 在这其中又扮演了什么角色?
今天,我们就一起深入 Android App 的打包流程,并结合 Android Gradle Plugin (AGP) 的构建流程,来一次彻底的解密!我们将像解剖 “麻雀” 一样,细致地分析 APK 的 “诞生” 过程,让你对 Android 构建的 “幕后” 了如指掌,从而更好地优化构建,解决构建难题,甚至定制更高级的构建特性。
Android 应用打包流程概览:从源码到 APK 的 “变形记”
在深入 AGP 构建流程之前,我们不仅要从宏观层面了解 Android 应用的打包流程,更要深入到 APK 文件的 “肌理” 之中,了解它的构成,理解 DEX 字节码的奥秘,才能真正把握 Android 构建的本质。
什么是 APK 文件? APK 文件结构详解
首先,我们来揭秘 APK (Android Application Package) 文件的真面目。APK 文件,顾名思义,就是 Android 应用程序包。但它并非传统意义上的可执行文件,而是一种 标准的 ZIP 压缩文件。你可以像解压缩普通 ZIP 文件一样,轻松地打开 APK 文件,一探其内部结构。
APK 文件结构概览:

打开 APK 文件后,你会看到类似如下的目录和文件结构:
classes.dex: Dalvik Executable 文件,这是 APK 文件中 最核心的部分,包含了项目 所有 Java 和 Kotlin 代码编译后的 Dalvik 字节码。Android 虚拟机 (Dalvik 或 ART) 就是执行classes.dex文件中的代码。
res/(resources): 资源目录,包含了项目中所有 非代码的资源文件,例如:layout/: XML 布局文件drawable/,mipmap/: 各种图片资源 (PNG, JPG, XML VectorDrawable等)values/: XML 资源值文件 (strings.xml, colors.xml, styles.xml, dimens.xml等)anim/,animator/: 动画资源xml/: XML 配置文件raw/: 原始资源文件 (例如音频、视频等)
这些资源文件在构建过程中会被 aapt2 工具编译和处理,并最终打包到
res/ 目录下。resources.arsc(Android Resource Source Compilation): 资源索引表文件,这是一个 二进制文件,包含了res/目录下所有 资源文件的索引信息。resources.arsc文件 加速了 Android 系统对资源文件的访问速度,系统可以通过查阅resources.arsc文件快速定位和加载所需的资源,而无需遍历整个res/目录。
META-INF/(Meta Information): 元信息目录,包含了 APK 文件的 签名和校验信息,用于 保证 APK 文件的完整性和安全性。META-INF/目录下通常包含以下文件:MANIFEST.MF: APK 包中所有文件的 SHA1 或 SHA256 哈希值 列表。CERT.SF: 签名文件,包含了签名者的证书信息和MANIFEST.MF文件的签名。CERT.RSA或CERT.DSA: 签名证书文件,包含了签名者的公钥信息。
当生成 APK 时,系统会对 APK 包中的所有内容进行校验,并将校验结果保存在
META-INF/ 目录中。手机在安装应用时,会再次对 APK 内容进行校验,并将结果与 META-INF/ 目录中的校验结果进行比较,以验证 APK 文件是否被恶意篡改。assets/(assets): 原生资源目录,用于存放项目中使用的 原生资源文件,例如文本文件、字体文件、HTML 文件、音频文件、视频文件等。assets/目录下的资源文件 不会被 aapt2 工具编译处理,会 原封不动地打包到 APK 中。 开发者需要使用 AssetManager 类来访问和管理assets/目录下的资源文件。
AndroidManifest.xml(Android Manifest): Android 清单文件,这是每个 Android 应用 必不可少的核心配置文件,用于 描述应用的各种基本信息和组件信息,例如:package属性: 应用的包名 (Package Name),应用的唯一标识符。versionCode,versionName: 应用的版本号和版本名。<application>标签: 应用级别的配置,例如应用名称、图标、主题、允许的进程等。<activity>,<service>,<receiver>,<provider>标签: 声明应用的四大组件 (Activity, Service, BroadcastReceiver, ContentProvider)。<uses-permission>标签: 声明应用需要的权限。<uses-sdk>标签: 声明应用支持的最小 SDK 版本和目标 SDK 版本。
AndroidManifest.xml 文件在构建过程中会被 aapt2 工具编译和处理,并最终打包到 APK 中。什么是 DEX 文件? JVM、Dalvik、ART 的 “恩怨情仇”
classes.dex 文件是 APK 文件中 代码的 “灵魂”,它包含了 Android 应用在虚拟机上运行的所有代码。要理解 DEX 文件,我们先要了解 JVM (Java Virtual Machine), Dalvik, 和 ART (Android Runtime) 这三个关键概念。- JVM (Java Virtual Machine): Java 虚拟机,是 Java 语言的核心基石,负责 执行 Java 字节码。 传统的 Java 应用运行在 JVM 之上。 JVM 执行的是 Java 字节码 (
.class文件)。
- Dalvik: Dalvik 虚拟机,是 Google 为 Android 平台专门设计的 Java 虚拟机,用于 替代 JVM。 Dalvik 虚拟机 最初被用于 Android 早期版本 (Android 5.0 之前)。 Dalvik 虚拟机不能直接执行 Java 字节码,它执行的是 DEX (Dalvik Executable) 字节码。Dalvik 虚拟机采用 JIT (Just-In-Time) 即时编译 技术,在程序 运行时 将 DEX 字节码 动态编译成机器码 执行。
- ART (Android Runtime): Android Runtime 虚拟机,是 Google 为了替代 Dalvik 虚拟机而设计的新一代 Android 虚拟机,从 Android 5.0 (Lollipop) 开始成为 Android 默认虚拟机。ART 虚拟机也执行 DEX (Dalvik Executable) 字节码,但与 Dalvik 虚拟机最大的区别在于,ART 虚拟机采用 AOT (Ahead-Of-Time) 预编译 技术,在应用 安装时 就将 DEX 字节码 预先编译成机器码,并存储在本地。 这样,在应用 运行时,ART 虚拟机 直接执行本地机器码,无需像 Dalvik 虚拟机那样进行即时编译,性能更高,更省电,并优化了垃圾回收机制。 但 AOT 预编译的缺点是,应用安装时间会更长,占用存储空间也会更大。
DEX (Dalvik Executable) 文件,全称 Dalvik 可执行文件,是 专为 Dalvik 和 ART 虚拟机设计的一种字节码文件格式。DEX 文件是 APK 文件中
classes.dex 文件的格式。 Dalvik 和 ART 虚拟机不能直接运行 Java 字节码 (.class 文件),需要将 Java 字节码转换成 DEX 字节码才能执行。DEX与.class文件结构的对比:

DEX文件生成步骤
为了生成 DEX 文件,Android 构建工具 (例如 DX, D8, R8) 需要对传统的 Java 字节码 (
.class 文件) 进行 翻译、重构、解释、压缩 等处理,主要包括以下步骤:.class文件收集: 收集项目中 所有 Java 和 Kotlin 源代码编译生成的.class文件,以及 项目依赖的第三方库 (JAR 包, AAR 包) 中的.class文件。
- DEX 转换: 使用 DX (Dalvik Compiler) 或 D8 (Dexer) 工具将
.class文件 转换成 DEX 字节码。 D8 是 Google 新一代 DEX 编译器,取代了早期的 DX 工具,D8 编译速度更快,输出的 DEX 文件更小,并且更容易进行代码优化。 R8 (Shrinker) 工具在 DEX 编译的基础上,还同时进行 代码优化、混淆和压缩,是更强大的构建工具。 现代 Android 构建流程主要使用 D8 和 R8 工具进行 DEX 编译。
- DEX 文件优化: DEX 文件格式针对移动设备的 内存和处理器限制 进行了优化,例如:
- 共享常量池: DEX 文件中,所有类共享一个 常量池 (Constant Pool),避免了
.class文件中每个类都有自己常量池的冗余, 减少了 DEX 文件的大小。 - 紧凑的文件结构: DEX 文件采用 线性、紧凑的文件结构,减少了文件碎片,提高了虚拟机加载 DEX 文件的速度。
实验表明,DEX 文件比传统的 JAR 包文件小 50% 左右,更适合在资源受限的移动设备上运行。
Android 应用的构建流程
理解了 APK 文件结构和 DEX 文件原理,我们再来看更详细的 Android 应用构建流程。 Google 官方给出了不同版本的构建流程图,我们可以结合这两个图来理解 Android 应用构建的完整过程。
官方简版 Android 应用构建流程:

这个简版流程概括了 Android 应用构建的核心步骤:
- 源码和资源编译: 编译器 将项目 源码 (Java/Kotlin 代码) 转换成 DEX 文件,并将 其他所有内容 (资源文件, Manifest 文件) 转换成 已编译资源。 这里的 “编译器” 实际上包含了 Kotlin 编译器, Java 编译器, D8/R8, aapt2 等工具。
- APK 打包: APK 打包器 (apkbuilder 或 apkzlib) 将 DEX 文件 和 已编译资源 合并成 单个 APK 文件。 在打包之前,需要先对 APK 文件进行签名。
- APK 签名: APK 打包器 使用 调试密钥库 (Debug Keystore) 或 发布密钥库 (Release Keystore) 对 APK 文件进行 签名。 Debug 版本使用调试密钥库签名,Release 版本使用发布密钥库签名。
- APK 对齐优化: 在生成最终 APK 文件之前,APK 打包器 (zipalign) 使用 zipalign 工具 对 APK 文件进行 对齐、优化,以 减少应用在设备上运行时对内存的占用,提高运行效率。 发布正式版的 APK 文件,必须经过字节对齐处理。
Google 官方老版本的详细 Android 应用构建流程:

这个老版本的流程图更加详细地描述了构建过程中的各个工具和产物:
- 打包资源文件,生成
R.java文件: 使用 aapt (Android Asset Packaging Tool) 工具 (早期版本,现在主要使用 aapt2) 处理 资源文件 (res 目录) 和AndroidManifest.xml文件,进行 编译和打包,并 生成R.java文件 (用于在代码中引用资源 ID)。
- 处理
.aidl文件,生成对应的.java文件: 使用 aidl (Android Interface Definition Language) 工具处理.aidl文件 (Android 接口定义语言文件),将.aidl文件 解析成相应的.java文件 (用于实现跨进程通信)。
- 编译
.java文件,生成.class文件: 使用 javac (Java Compiler) 编译器编译 所有.java文件 (包括R.java文件,.aidl文件生成的.java文件,以及项目自身的 Java 源代码文件),生成.class字节码文件。
- 处理
.class文件,生成classes.dex文件: 使用 dx (Dalvik Executable compiler) 工具 (早期版本,现在主要使用 D8/R8) 将 所有.class文件 (包括项目自身的.class文件,以及 第三方库 (JAR 包, AAR 包) 中的.class文件) 转换成classes.dex文件 (Dalvik 可执行文件)。
- 打包 APK 文件: 使用 apkbuilder (APK Builder) 工具 (早期版本,现在主要使用 apkzlib) 将 所有资源 (包括未编译的资源和已编译的资源) 和
.dex文件 打包成 APK 文件。
- APK 文件签名: APK 文件只有被签名了,才能安装到 Android 设备上。 使用 jarsigner 工具 (早期版本,现在主要使用 apksigner) 对 APK 文件进行签名。
- APK 文件对齐处理: 使用 zipalign 工具对 APK 文件进行字节对齐处理。 发布正式版的 APK 文件,必须经过字节对齐处理,这样可以减少应用在运行中对内存的使用。
对比两个流程图,我们可以看到,Android 应用的构建流程虽然细节繁多,但核心步骤是基本一致的,都是围绕着资源编译、代码编译、打包、签名、优化这几个关键环节展开的。而 AGP 的作用,就是将这些环节串联起来,自动化整个构建过程。
小结:
- 深入了解 APK 文件结构和 DEX 文件原理,可以帮助你从更底层理解 Android 应用的运行机制,以及构建过程的必要性。
- 理解 JVM, Dalvik, ART 的区别,有助于你理解 Android 虚拟机的发展历程,以及 DEX 文件在 Android 系统中的地位。
- 掌握官方提供的 Android 应用构建流程图,可以帮助你更系统地理解 Android 构建的各个环节,以及各个构建工具的作用。
- AGP 的核心目标就是自动化和简化 Android 应用的构建流程,将复杂的构建过程封装在 Gradle 插件内部,让开发者可以更专注于应用开发,而无需过多关注构建细节。 但深入理解构建流程,仍然有助于我们更好地优化构建,解决构建问题,甚至定制高级构建特性。
Android Gradle Plugin (AGP) 构建流程详解:APK “变形记” 的 “导演”
Android Gradle Plugin (AGP) 是 Android 构建的核心 Gradle 插件,它就像 Android 构建流程的 “导演”,负责编排和控制整个构建过程,将上述的 Android 应用打包流程的各个步骤串联起来,并提供丰富的配置选项和扩展接口,让我们可以高度定制 Android 构建。 官方文档参考:Android Gradle plugin overview
AGP 的核心功能与架构:构建流程的 “控制中枢”
核心功能:
AGP 的核心功能可以概括为以下几点:
- 定制 Android 构建流程: AGP 扩展了 Gradle 的构建能力,使其能够理解和处理 Android 特有的构建元素,例如 AndroidManifest.xml, resources, AIDL, RenderScript 等。 AGP 定义了一套 Android 特有的构建 Task 和构建流程,例如资源处理 Task, 代码编译 Task, 打包 Task, 签名 Task 等。 官方文档参考:Configure your build
- 提供 Android 特有的 DSL (Domain Specific Language): AGP 为
Project对象添加了android {}扩展,提供了丰富的 DSL 配置选项,例如compileSdk,buildTypes,productFlavors,dependencies,signingConfigs等,让开发者可以使用简洁的 DSL 语法配置 Android 构建的各个方面。 官方文档参考:Android Plugin DSL reference
- 管理 Build Variants (构建变体): AGP 引入了 Build Variants (构建变体) 的概念,包括 Build Types (构建类型) (例如
debug,release) 和 Product Flavors (产品风味) (例如dev,prod),让开发者可以方便地构建同一个应用的多个不同版本,例如 Debug 版本和 Release 版本,或者不同渠道的版本。 AGP 会为每个 Build Variant 创建一套独立的构建 Task 和构建配置。 官方文档参考:Configure build variants
- 提供扩展接口 (Extension APIs): AGP 提供了丰富的 扩展接口 (Extension APIs),例如 Transform API, Task API, Variant API, DSL APIs 等,让开发者可以通过插件或构建脚本,深度定制和扩展 AGP 的构建流程,例如自定义代码转换、资源处理、Task 行为等。 官方文档参考:Extend the plugin with the Android Gradle plugin APIs
核心架构:
- AGP 的核心架构可以简化理解为以下几个层次:
- 解析:
- Gradle Core: Gradle 核心引擎,提供 Task 调度、依赖管理、项目模型等基础功能。 官方文档参考:Gradle User Manual
- Android Gradle Plugin (AGP): AGP 核心插件,基于 Gradle Plugin API 开发,扩展 Gradle 构建能力,定制 Android 构建流程,并提供 Android 特有的 DSL 配置。 官方文档参考:Android Gradle plugin release notes
- AGP Extension APIs: AGP 提供的扩展接口,让开发者可以深度定制 AGP 构建流程。 官方文档参考:Work with the Transform API
- Android Build Tools: Android SDK Build Tools,例如 aapt2, d8/r8, zipalign, apksigner 等,AGP 会调用这些 Build Tools 来执行具体的构建任务。 官方文档参考:SDK Tools release notes
小结:
- AGP 是 Android 构建的 “灵魂”,理解 AGP 的核心功能和架构,是深入理解 Android 构建流程的关键。
- AGP 通过扩展 Gradle,定制 Android 构建流程,并提供了丰富的 DSL 配置和扩展接口,让我们可以灵活地控制 Android 构建的方方面面。
- AGP 的核心价值在于 “自动化” 和 “可定制化” Android 构建。 它自动化了繁琐的 Android 构建流程,同时也提供了足够的定制能力,满足各种复杂的构建需求。
AGP 的关键构建 Task 流程:APK “变形记” 的 “剧本” (修改后)
AGP 定义了一系列 关键的构建 Task,这些 Task 按照一定的顺序执行,共同完成了 Android 应用的打包流程。理解这些关键 Task 的作用和执行顺序,就像理解 APK “变形记” 的 “剧本”。 下面我们来详细解析 AGP 的关键构建 Task 流程,并将之前提到的 Android 应用打包流程的步骤融入其中:
资源处理流程:
资源处理流程 (Resource Processing Flow): 对应 Android 应用打包流程的 资源编译与处理 步骤。
AGP 主要通过以下 Task 来实现资源处理:
代码编译流程:
代码编译流程 (Code Compilation Flow): 对应 Android 应用打包流程的 代码编译 步骤。
AGP 主要通过以下 Task 来实现代码编译:
打包流程:
打包流程 (Packaging Flow): 对应 Android 应用打包流程的 APK 打包 和 APK 签名 步骤。
AGP 主要通过以下 Task 来实现打包和签名:
说明:
${VariantName}: 表示 Build Variant 名称,例如Debug,Release,DevDebug,ProdRelease等。 AGP 会为每个 Build Variant 生成一套独立的 Task,例如compileDebugKotlin,compileReleaseKotlin,packageDebug,packageRelease等。
- 上述 Task 流程只是一个简化版的概览,实际的 AGP 构建流程更加复杂,包含了更多的 Task 和更细致的步骤。 官方文档参考:Understand the build process
- AGP 构建流程是 高度可配置和可扩展 的,你可以通过 AGP 的 Extension APIs (例如 Transform API, Task API) 来自定义和修改构建流程。 官方文档参考:Extend the plugin with the Android Gradle plugin APIs
最后:
- Android 应用打包流程看似复杂,但通过 Android Gradle Plugin (AGP) 的精心编排,一切都变得井然有序,并且高度可定制。
- AGP 不仅是 Android 构建的 “导演”,更是我们 Android 开发者手中的 “魔杖”,掌握 AGP 构建流程,理解 APK 打包的 “变形记”,就能让我们在 Android 构建的世界里更加游刃有余,打造出更优质、更高效的 Android 应用。
- 在未来的博客中,我将继续分享更多关于 Gradle 和 AGP 的进阶用法和最佳实践,敬请期待!
参考资料与深入阅读:
- Android Gradle plugin overview: https://developer.android.com/studio/build/agp-overview
- Configure your build: https://developer.android.com/studio/build/configure-build-files
- Android Plugin DSL reference: https://developer.android.com/reference/tools/gradle-android-plugin-dsl/index
- Configure build variants: https://developer.android.com/studio/build/build-variants
- Extend the plugin with the Android Gradle plugin APIs: https://developer.android.com/studio/extend
- Understand the build process: https://developer.android.com/studio/build/build-process
- Android Asset Packaging Tool 2 (aapt2): https://developer.android.com/studio/command-line/aapt2
- D8 and R8 shrinkers: https://developer.android.com/build/shrinker
- Sign your app: https://developer.android.com/studio/publish/app-signing
- The AndroidManifest.xml file: https://developer.android.com/guide/topics/manifest/manifest-intro
- Build native libraries with NDK and CMake: https://developer.android.com/ndk/guides/cmake
- Gradle User Manual: https://docs.gradle.org/current/userguide/userguide.html
- Android Gradle plugin release notes: https://developer.android.com/studio/releases/gradle-plugin
- Work with the Transform API: https://developer.android.com/studio/build/extend-agp-api
- SDK Tools release notes: https://developer.android.com/studio/releases/sdk-tools
- Kotlin Compiler: https://kotlinlang.org/docs/compiler-reference.html
- Gradle Build Scan: https://gradle.com/build-scans
- Develop custom plugins: https://docs.gradle.org/current/userguide/custom_plugins.html
- Author:CoderWdd
- URL:https://www.wuinsights.top//article/194ef23a-5a65-4a4b-ad62-739f842b2441
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts