在Android Studio中,我们需求打一个apk包,能够在Gradle task 使命中选一个 assembleDebug/assembleRelease 使命,

Android 完整的apk打包流程

操控台上就能够看到一切的构建相关task:

Android 完整的apk打包流程
Android 完整的apk打包流程
能够看到,这么多个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类里以静态属性的方法展示:

Android 完整的apk打包流程

第三步:兼并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 文件:

Android 完整的apk打包流程
实际上被打包到 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文件)

Android 完整的apk打包流程

  • 在本来 dx是最早的转化东西,用于转化class文件为dex文件。
  • Android Studio 3.1之后,引入了D8编译器和R8东西。
  • Android Studio 3.4之后,默许敞开 R8 详细的差异能够点击看看

留意:JVMDalvik(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,而apksignerGoogle专门为Android供给的签名和签证东西。

其差异就在于jarsigner只能进行v1签名,而apksigner能够进行v2v3v4签名。

  • 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签名分块,坐落中心目录部分之前,如下图:

Android 完整的apk打包流程

这样处理之后,文件就完结无法修正了,这也是为什么 zipalign(对齐处理) 要在签名之前完结。

  • v3签名

Android 9推出了v3签名方案,和v2签名方法基本相同,不同的是在v3签名分块中添加了有关受支持的sdk版别和新旧签名信息,能够用作签名替换升级。

  • v4签名

Android 11推出了v4签名方案。

最终,apk得以完结打包

PMS 在安装过程中会检查 apk 中的签名证书的合法性,详细安装apk内容稍后介绍。

apk内容包括如下:

Android 完整的apk打包流程

总体的打包流程图如下:

Android 完整的apk打包流程

,,