编译–>DEX–>打包–>签名和对齐
Package Process
上面这张图对上面的步骤以及每步用到的工具进行了细分,概括如下:
Java编译器对工程本身的java代码进行编译,这些java代码有三个来源:app的源代码,由资源文件生成的R文件(aapt工具),以及有aidl文件生成的java接口文件(aidl工具)。产出为.class文件。
.class文件和依赖的三方库文件通过dex工具生成Delvik虚拟机可执行的.dex文件,可能有一个或多个,包含了所有的class信息,包括项目自身的class和依赖的class。产出为.dex文件。
apkbuilder工具将.dex文件和编译后的资源文件生成未经签名对齐的apk文件。这里编译后的资源文件包括两部分,一是由aapt编译产生的编译后的资源文件,二是依赖的三方库里的资源文件。产出为未经签名的.apk文件。
分别由Jarsigner和zipalign对apk文件进行签名和对齐,生成最终的apk文件。
可以将整个打包过程概括为以下几步:
- 通过aapt打包res资源文件,生成R.java、resources.arsc和res文件(二进制 & 非二进制如res/raw和pic保持原样)
- 处理.aidl文件,生成对应的Java接口文件
- 通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件
- 通过dex命令,将.class文件和第三方库中的.class文件处理生成classes.dex
- 通过apkbuilder工具,将aapt生成的resources.arsc和res文件、assets文件和classes.dex一起打包生成apk
- 通过Jarsigner工具,对上面的apk进行debug或release签名
通过zipalign工具,将签名后的apk进行对齐处理。
关于zipalign工具,根据名字就知道是个zip文件对齐的工具。使得apk中的资源文件偏离文件起始位置4个字节,从而可以通过mmap()直接访问,从而减少RAM占用。
下图是谷歌官网给出的一个典型的apk构建的过程,比较概括。主要包括两个过程,首先是编译过程,编译的内容包括本工程的文件以及依赖的各种库文件,编译的输出包括dex文件和编译后的资源文件。然后是打包过程。配合Keystore对第一步的输出进行签名对齐,生成最终的apk文件。
APK Content
apk包内容包括:
- classes.dex…
- resources.arsc
- assets
- res
- AndroidManifest.xml
- META-INF
7.
其中:
res中图片和raw文件下内容保持原样,res中其他xml文件内容均转化为二进制形式;assets文件内容保持原样
res中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类
Gradle Process
Android工程通过gradle文件管理各项配置,gradle文件利用DSL(Domain Specific Language)语言描述配置,并使用Groovy语言处理编译逻辑。一个典型的Android工程结构如下:
在这里gradle文件分布在几个不同的层级,Project层级以及Module层级。
- Project层级的settings.gradle描述的是该Project包含哪些Module1include ':presentation', ':qamodel', ':chatcommonmodule', ':qa', ':unlimit'
Project层级的build.gradle描述的是作用于所有Module的配置,包括gradle版本等。
- Module层级的build.gradle。每个Module下都有一个作用于该Module的build.gradle文件,描述了该Module相关的配置。这些配置主要包括:BuildTypes,ProductFlavors,Dependency,SigningSettings等。
Reference
[1]Android应用开发编译框架流程与IDE及Gradle概要
[2]Android Gradle权威指南
[3]Gradle 完整指南(Android)