APK文件浅析-打包流程

本文从宏观视角来看看APK文件结构及其设计思想,借助一个简单的“Hello Android”为例说明java

APK文件结构

An APK file contains all of a program’s code (such as .dex file), resources, assets, certificates, and manifest file.android

APK文件自己是个压缩文件,咱们能够经过一个简单的Hello Android示例和一个复杂的应用,对比其对应的APK文件。 首先新建一个简单的Hello Android项目,build出一个APK文件后拖到AS中利用自带的apkanalyzer打开,基本组成如图: 微信

Hello Android
再打开一个下载好的比较复杂的APK(微信), 如图
WeChat
不管是简单的Hello world 仍是复杂的WeChat,能够看出其主要组成包括:

  1. AndroidManifest.xml :用于声明应用包名信息、相关的使用权限、四大组件、android sdk版本等;
  2. res目录:包含程序主要资源文件,包括res/layout、res/drawable等,主要是布局文件和图片等资源。(微信是对资源作了混淆,字符串裁剪,上图中的r=res);
  3. resources.ars:资源映射表,包含一部分编译资源(res/value)和资源路径, 能够经过资源R.java中的ID映射到对应的资源文件或者值;
  4. assets目录:包含不被压缩的原始文件,主要是一些多媒体文件,或者附加文件;
  5. lib目录:使用到的各类.so连接库;
  6. Classes.dex:打包好的程序代码,若是是复杂的应用会进行分包,包含多个dex文件(微信);
  7. META-INF目录:主要包含APK的签名信息
    • MANIFEST.MF:清单文件,当前APK中全部文件清单及其对应hash值;
    • CERT.SF:上述清单文件中的每条信息的hash值;
    • CERT.RSA:对CERT.SF文件的数字签名以及签名时所用的数字证书;

那这些文件究竟是怎么生成的,接下来看看一个APK文件的构建流程。框架

APK打包流程

Android Studio默认采用gradle组织完成打包过程,对开发者来讲简单的执行相关的task便可,这种透明的打包过程也让咱们忽略了不少细节,这里咱们以上述APK文件结构做为对照,来一窥源码结构变成最终的APK文件的过程。ide

1. AndroidManifest.xml

Hello Android为例,对比源码中的AndroidManifest.xml 与 APK中的AndroidManifest.xml 能够明显看出 工具

AndroidManifest
会新增一些之类的标签,以前的theme、label等字符串被替换为具体的引用。这一过程发生在资源打包过程当中,对这一过程不熟悉的可参考我以前的 资源打包流程, 简单说就是gradle在打包过程当中会经过命令行启动 aapt工具, aapt在打包资源过程当中会进行Merge Manifest,对AndroidManifest.xml文件进行修改。 注意这里是经过AndroidStudio自带的分析器打开APK才能明确看到AndroidManifest.xml中的内容,若是只是简单的解压APK后AndroidManifest.xml被编译成了二进制文件。

2. res/

对比源码和打包后res目录的变化,也会发现res中的drawable中的图片等资源没有发生明显变化(其实会部分压缩),layout/下的xml文件也发生了相似AndroidManifest.xml的字符串替换和编译,变成了二进制文件,而values/不见了。对res/的处理也发生在aapt编译资源的过程当中,对其中的xml文件进行编译和字符串裁剪,部分xml资源会被编译进resources.arsc。布局

3. resources.arsc

resources.arsc 也是个二进制文件,是aapt打包资源过程当中的产物,同时伴随着上述资源文件的编译和压缩,其中res/value其实就编译进了resources.arsc, 其余的资源文件的id和路径对应关系也写进了这个文件,便于运行时访问。gradle

对资源打包和访问不太熟悉的能够参考:优化

Android 资源框架:资源打包流程ui

Android 资源框架:资源的运行时访问

4. assets/

目录中的文件未发生变化

5. lib/

无变化

6. Classes.dex

dex文件是Dalvik 和 ART 可执行格式。相较于JVM,dex将多个class文件打包到了一块儿,所以从Java文件到dex,须要经历java--->class-->dex的过程;

  • 若是用到了AIDL,经过sdk/build-tools/xxx/aidl 工具解析aidl文件,生成对应的Java文件;
  • Compile全部的 Java文件生成 .class文件;
  • 经过dx脚本,将全部class文件包括第三方Jar包等处理为dex文件,若是配置了multidex, 可能会生成多个classes.dex文件。dx及其余相关脚本位于sdk/build-tools/xxx/

相较于class文件,dx工具在生成dex文件的过程当中,会对字符常量池和一些冗余信息会进行压缩,结构上比class文件也更加紧凑。

7. 打包

经过apkbuilder工具,将aapt处理后的相关资源文件和利用dx处理生成的Classes.dex打包生成APK文件,apkbuilder工具也位于 sdk/build-tools/

8. 对APK进行对齐处理

借助zipalign工具,对APK文件进行对齐处理:

zipalign 是一种归档对齐工具,可对 Android 应用文件进行重要的优化。其目的是要确保全部未压缩数据的开头均相对于文件开头部分执行特定的对齐。具体来讲,它会使 APK 中的全部未压缩数据(例如图片或原始文件)在 4 字节边界上对齐。这样一来,便可使用 mmap() 直接访问全部部分,即便其中包含具备对齐限制的二进制数据也不要紧。这样作的好处是能够减小运行应用时消耗的 RAM 容量。

9.签名

经过apksigner工具,对生成的APK文件进行签名;

以上,咱们就获得了一个包含 代码 + 资源 + 签名信息的可独立安装运行的APK文件。

以上用到的相关脚本及工具均位于 sdk/build-tools/

sdk build-tools
具体的细节可参考其对应source code

总结

咱们首先分析了一个基本的APK文件的组成部分,以后拆解了每个组成文件的生成过程及其相关脚本。若是你对aaptdxapksigner的具体工做流程感兴趣,能够查找并阅读其源码。再来看官方打包流程图,相信你会更加清晰!

apk build

相关阅读:

Android MultiDex 分包及加载原理

Android 资源框架:资源打包流程

Android 资源框架:资源的运行时访问

相关文章
相关标签/搜索