《Android APK组成&编译打包流程详解》

2341 admin
刘诗雯世界杯

目录

一、APK 的组成

二、APK 打包流程

1. 资源处理

2. 代码编译

3. 资源与代码合并

4. 原生库处理

5. APK 签名

6. APK 对齐优化

三、详细构建流程图

四、构建工具链演进

五、优化与扩展

六、虚拟机演进

Android APK(Android Package)是 Android 应用的安装包文件,其组成和打包流程涉及多个步骤和文件结构。以下是详细的说明:

一、APK 的组成

APK 是一个 ZIP 格式的压缩包,包含应用运行所需的所有文件。解压后主要包含以下内容:

classes.dex

由 Java/Kotlin 代码编译后的 Dalvik/ART 字节码文件。

如果方法数超过 65536,会生成多个 classes2.dex、classes3.dex 等(需启用 MultiDex)。

resources.arsc

编译后的二进制资源索引表,包含字符串、布局、颜色等资源的映射关系,用于快速查找资源。

AndroidManifest.xml

应用的配置文件(二进制格式),声明包名、权限、组件(Activity/Service 等)、最低 SDK 版本等。

res/ 目录

存放编译后的资源文件(图片、布局 XML、动画等),原始 XML 会被编译为二进制格式以优化读取效率。

assets/ 目录

存放原始资源文件(如字体、配置文件),通过 AssetManager 直接访问,不参与资源 ID 生成。

lib/ 目录

存放原生库(.so 文件),按 CPU 架构分目录(如 armeabi-v7a, arm64-v8a, x86)。

META-INF/ 目录

包含应用签名信息(MANIFEST.MF, CERT.SF, CERT.RSA),用于验证 APK 完整性。

kotlin/ 目录

如果使用 Kotlin,会包含 Kotlin 标准库的相关文件。

其他文件

如 ProGuard/R8 生成的映射文件(mapping.txt)、AAPT2 生成的资源映射等。

二、APK 打包流程

Android 应用的构建流程通过 Gradle 和 Android 构建工具链(如 AAPT2、D8、R8 等)完成,主要步骤如下:

1. 资源处理

工具:AAPT2 (Android Asset Packaging Tool)

编译 res/ 下的资源文件(XML、图片等),生成 resources.arsc 和二进制 XML。

生成 R.java 文件,为每个资源分配唯一 ID。

2. 代码编译

Java/Kotlin 编译

将 Java/Kotlin 源代码编译为 .class 文件(javac 或 kotlinc)。

DEX 转换

使用 D8 或 R8 工具 将 .class 文件转换为 Android 虚拟机所需的 .dex 文件,优化字节码并可能启用代码混淆(通过 R8)。

3. 资源与代码合并

工具:Android Gradle Plugin

合并所有模块的资源文件,处理资源冲突。

将 classes.dex、resources.arsc、lib/、assets/ 等文件打包到临时 APK 中。

4. 原生库处理

将 JNI 库(.so 文件)按 CPU 架构分类,并打包到 APK 的 lib/ 目录。

5. APK 签名

工具:apksigner 或 jarsigner

使用开发者密钥对 APK 进行签名,确保应用来源可信且未被篡改。

生成 META-INF/ 目录下的签名文件。

6. APK 对齐优化

工具:zipalign

对 APK 中的未压缩文件进行内存对齐(4 字节边界),提升运行时加载效率。

zipalign 主要工作是将apk包进行对齐处理。使apk包中的所有资源文件,起始偏移为4字节的整数倍,这样通过mmap内存映射访问apk时的速度会更快。

工具名称功能介绍在操作系统中的路径aaptAndroid资源打包工具${ANDROID_SDK_HOME}/build-tools/30.0.0/aaptaidlAndroid接口描述语言转化为.java文件的工具${ANDROID_SDK_HOME}/build-tools/30.0.0/aidljavacjava Compiler java代码转class文件${JDK_HOME}/javac或/usr/bin/javacdex转化.class文件为Davik VM能识别的.dex文件${ANDROID_SDK_HOME}/build-tools/30.0.0/dxapkbuilder生成apk包???没有找到jarsigner.jar文件的签名工具${JDK_HOME}/jarsigner或/usr/bin/jarsignerzipalign字节码对齐工具${ANDROID_SDK_HOME}/tools/zipalign

三、详细构建流程图

源代码 (Java/Kotlin) --> 编译 --> .class 文件 --> D8/R8 --> classes.dex

资源文件 (res/, assets/) --> AAPT2 --> resources.arsc + 二进制 XML

原生库 (JNI) --> 按架构分类打包到 lib/

合并所有文件 --> 未签名 APK --> 签名 --> 签名后的 APK --> zipalign 对齐 --> 最终 APK

四、构建工具链演进

AAPT → AAPT2:支持增量资源编译,提升构建速度。

DX → D8:更快的 DEX 编译,更好的字节码优化。

ProGuard → R8:将代码压缩(Shrinking)、优化(Optimization)、混淆(Obfuscation)与 DEX 编译合并为一步。

五、优化与扩展

Android App Bundle (AAB):Google 推出的动态分发格式,按设备配置生成优化后的 APK。

Split APKs:根据屏幕密度、ABI 等拆分 APK,减少用户下载体积。

资源混淆:通过工具(如 AndResGuard)对资源文件名进行混淆,进一步缩减 APK 体积。

六、虚拟机演进

虚拟机是一个可以运行 class , odex , oat 可执行文件的运行环境 ;

常见的虚拟机有 Java 虚拟机、Dalvik 虚拟机 、 ART 虚拟机 ;

Java 虚拟机 : 运行的 class 字节码文件 , 运行程序时解码 class 文件中的内容 ; 基于栈架构 , 需要频繁在栈上读写数据 , 造成较多的指令分派 , 更多的内存访问次数 , 比较耗费 CPU 时间 ;

编译时 : Java 源码 , 使用 javac 编译器 , 编译成 class 字节码文件 ; 运行时 : 类加载器通过 Java 类库验证字节码 , 验证通过会后进入 Java 虚拟机 , 进入 Java 解释器 或 即时编译器 , 然后进入运行时系统 , 之后进入操作系统 , 然后调用硬件 ;

Dalvik 虚拟机 : 基于 JIT 机制 ( 即时编译技术 )

Android 5.0 以下使用的虚拟机是 Dalvik 虚拟机 , 该虚拟机的可执行文件是 dex 文件 , 该文件比 class 字节码文件更小 ; JIT ( Just In Time ) 即时编译技术 , 对应 Dalvik 虚拟机 ; 基于寄存器架构 , 通过寄存器间接访问数据 , 该方式比基于栈架构速度更快 ;

ART 虚拟机 :

Android 5.0 以上使用的虚拟机是 ART 虚拟机 ; AOT ( Ahhead Of Time ) 预编译技术 , 对应 ART 虚拟机 ; Java 虚拟机 / Dalvik 虚拟机 / ART 虚拟机 都向上层提供了 3 个接口JNI_GetDefaultJavaVMInitArgs JNI_CreateJavaVM JNI_GetCreatedJavaVMS ; 虚拟机之间可实现无缝衔接 ;

Dalvik 虚拟机 与 ART 虚拟机区别 : 虚拟机中有个 persist.sys.dvlvik.vm.lib 字段 , 如果该字段存储的是 libdvm.so , 该虚拟机是 Dalvik 虚拟机 ; 如果该字段存储的是 ;ibart.so , 该虚拟机是 ART 虚拟机 ;

Dalvik 虚拟机 与 ART 虚拟机可执行文件 :

Dalvik 虚拟机加载 dex 文件加载时不是直接加载 dex 文件 , 加载执行的是 odex 文件 , odex 文件是通过 dexopt 工具对 dex 进行优化生成的 ;

ART 虚拟机加载 dex 文件时加载的是 oat 文件 , oat 文件时通过 dex2oat 工具对 dex 文件进行优化生成的 ;

通过理解 APK 的组成和打包流程,开发者可以更好地优化应用性能、调试构建问题,并掌握高级构建技术(如模块化、动态交付)。

参考:

1. 深入详解Apk编译打包流程

2. APK 打包流程 ( 文件结构 | 打包流程 | 安装流程 | 安卓虚拟机 )

3. Android 打包流程

推荐能看CCTV5的电视软件,体育赛事轻松看 超超超清突破数据图【更新为PDF附件,更方便】