在Android Studio中,我们需求打一个apk包,能够在Gradle task 使命中选一个 assembleDebug/assembleRelease 使命,
操控台上就能够看到一切的构建相关task:
能够看到,这么多个task使命,履行是有先后顺序的,其实首要便是以下过程:
//aidl 转化aidl文件为java文件
> Task :app:compileDebugAidl
//生成BuildConfig文件
> Task :app:generateDebugBuildConfig
//获取gradle中装备的资源文件
> Task :app:generateDebugResValues
// merge资源文件
> Task :app:mergeDebugResources
// merge assets文件
> Task :app:mergeDebugAssets
> Task :app:compressDebugAssets
// merge一切的manifest文件
> Task :app:processDebugManifest
//AAPT 生成R文件
> Task :app:processDebugResources
//编译kotlin文件
> Task :app:compileDebugKotlin
//javac 编译java文件
> Task :app:compileDebugJavaWithJavac
//转化class文件为dex文件
> Task :app:dexBuilderDebug
//打包成apk并签名
> Task :app:packageDebug
依托这些关键过程最终就能打包出一个apk。
首先看
第一步:aidl(编译aidl文件)
将项目中的aidl
文件编译为java
文件,AIDL用于进程间通讯
第二步:生成BuildConfig文件
在项目中装备了
buildConfigField
等信息,会在BuildConfig class类里以静态属性的方法展示:
第三步:兼并Resources、assets、manifest、so等资源文件
在我们的项目中会依赖不同的库、组件,也会有多渠道的需求,所以merge
这一步操作便是将不同地方的资源文件进行整合。
多个manifest文件也需求整理成一个完好的文件,所以假如有属性冲突这一步就会报错。资源文件也会整理分类到不同的分辨率目录中。
资源处理用的东西是aapt/aapt2
留意:AGP3.0.0
之后默许经过AAPT2
来编译资源,AAPT2
支持了增量更新,大大提升了功率。
AAPT 东西担任编译项目中的这些资源文件,一切资源文件会被编译处理,XML 文件(drawable 图片除外)会被编译成二进制文件,所以解压 apk 之后无法直接打开 XML 文件。但是 assets 和 raw 目录下的资源并不会被编译,会被原封不动的打包到 apk 紧缩包中。 资源文件编译之后的产品包括两部分:resources.arsc 文件和一个 R.java。前者保存的是一个资源索引表,后者定义了各个资源 ID 常量。这两者结合就能够在代码中找到对应的资源引证。比方如下的 R.java 文件:
实际上被打包到 apk 中的还有一些其他资源,比方 AndroidManifest.xml 清单文件和三方库中运用的动态库 .so 文件。
第四步:编译java文件(用到的东西 javac )
1、java文件包括之前说到的AIDL 生成的java文件
2、java代码部份:经过Java Compiler
编译项目中一切的Java
代码,包括R.java
、.aidl
文件生成的.java
文件、Java
源文件,生成.class
文件。在对应的build
目录下能够找到相关的代码
3、kotlin代码部份:经过Kotlin Compiler
编译项目中的一切Kotlin
代码,生成.class文件
注:注解处理器(APT
,KAPT
)生成代码也是在这个阶段生成的。当注解的生命周期被设置为CLASS
的时分,就代表该注解会在编译class
文件的时分收效,而且生成java
源文件和Class
字节码文件。
第五步: Class
文件打包成DEX
(dx/r8/d8等东西编译class文件)
- 在本来
dx
是最早的转化东西,用于转化class文件为dex文件。 - Android Studio 3.1之后,引入了
D8
编译器和R8
东西。 - Android Studio 3.4之后,默许敞开 R8 详细的差异能够点击看看
留意:JVM
和Dalvik(ART)
的差异:JVM履行的是.class文件、Dalvik和ART履行的.dex文件。详细的差异能够点击看看
而在编译class文件过程也常用于编译插桩,比方ASM,经过直接操作字节码文件完结代码修正或生成。
第六步:apkbuilder/zipflinger(生成APK包)
这一步便是生成APK文件,将manifest文件、resources文件、dex文件、assets文件
等等打包成一个紧缩包,也便是apk文件。
在老版别运用的东西是apkbuilder
,新版别用的是 zipflinger
。
而在AGP3.6.0
之后,运用zipflinger
作为默许打包东西来构建APK
,以提高构建速度。
第七步: zipalign(对齐处理)
对齐是Android apk 很重要的优化,它会使 APK 中的一切未紧缩数据(例如图片或原始文件)在 4 字节鸿沟上对齐。这使得CPU读写就会更高效。
也便是运用东西 zipalign 对 apk 中的未紧缩资源(图片、视频等)进行对齐操作,让资源按照 4 字节的鸿沟进行对齐。这种思想同 Java 对象内存布局中的对齐空间非常类似,首要是为了加快资源的拜访速度。假如每个资源的开端方位都是上一个资源之后的 4n 字节,那么拜访下一个资源就不用遍历,直接跳到 4n 字节处判断是不是一个新的资源即可。
第八步: apk 签名
没有签名的apk 无法安装,也无法发布到运用市场。
我们比较熟知的签名东西是JDK
供给的jarsigner
,而apksigner
是Google
专门为Android
供给的签名和签证东西。
其差异就在于jarsigner
只能进行v1
签名,而apksigner
能够进行v2
、v3
、v4
签名。
v1签名
v1签名方法首要是利用META-INFO
文件夹中的三个文件。
首先,将apk中除了META-INFO文件夹中的一切文件进行进行摘要写到 META-INFO/MANIFEST.MF;然后计算MANIFEST.MF文件的摘要写到CERT.SF;最终计算CERT.SF的摘要,运用私钥计算签名,将签名和开发者证书写到CERT.RSA。
所以META-INFO文件夹中这三个文件就能确保apk不会被修正。
v2签名
Android7.0
之后,推出了v2签名,为了处理v1签名速度慢以及签名不完好的问题。
apk本质上是一个紧缩包,而紧缩包文件格式一般分为三块:
文件数据区,中心目录结果,中心目录结束节。
而v2要做的便是,在文件中插入一个APK签名分块,坐落中心目录部分之前,如下图:
这样处理之后,文件就完结无法修正了,这也是为什么 zipalign(对齐处理)
要在签名之前完结。
v3签名
Android 9
推出了v3签名方案,和v2签名方法基本相同,不同的是在v3签名分块中添加了有关受支持的sdk版别和新旧签名信息,能够用作签名替换升级。
v4签名
Android 11
推出了v4签名方案。
最终,apk得以完结打包
PMS 在安装过程中会检查 apk 中的签名证书的合法性,详细安装apk内容稍后介绍。
apk内容包括如下:
总体的打包流程图如下:
,,