前言
APK,即Android Package,是将android程序和资源整合在一起,形成的一个.apk文件。相信所有的Android程序员是在IDE的帮助下,完成打包轻而易举,但对打包流程真正清楚的可能并不多。本章的内容比较简单,也是非常基础的内容,但是对理解android应用的结构却有很大的帮助。笔者写这篇文章的目的,一方面是为了弥补这方面的盲点,回顾和梳理apk打包方面的理论知识点;第二方面,是为了给后续写Android虚拟机知识做铺垫,进而去研究android的性能优化,这也是把这篇文章放到Android性能优化系列文章当中的原因;第三方面,也是为了方便读者理解Android虚拟机的相关内容。
对于在IDE,如Android Studio上操作打包的过程,本文不做演示,对于更深入的源码分析,也不在本文讨论之列,出于前面说到的原因,本文只简单阐述其打包流程,本文主要内容如下:

一、apk构建流程图
以下截图为Google官方提供的详细的apk构建过程图,其中包含了各个环节所用到的工具和中间相关的文件。

apk构建过程(绿色部分为对应环节工具,蓝色部分为相关文件)
二、构建过程中所用工具
如下截图展示了apk构建过程中所使用的部分工具,这些工具大部分都在sdk/build-tools/文件夹下:

代码混淆所用工具

打包所用工具所在的jar包
三、apk打包流程详解
依据如上的流程图和工具图,下面咱们按照流程顺序对其进行讲解。
1、aapt打包资源
- 工具:aapt(Android Asset Package Tool Android资源打包工具)
- 工具路径:sdkpath/build-tools/版本号/aapt.exe和aapt2.exe
- 输入:Android资源文件、AndroidManifest.xml
- 输出: R.java类、二进制的resource.arsc,res文件夹(包括二进制的xml、没被改变的图片和res/raw文件)、二进制的AndroidManifest.xml文件、没有改变的assets文件夹。
Android的资源文件包含了两类:1)assets类资源。该类资源放在工程目录的assets根目录下,存放一些原始文件,这些文件不会被编译为二进制文件,而是被原封不动地打包在apk文件中,同样也不能通过资源ID来查找,不保存在R文件中。2)res类资源,10种目录。这类资源保存在工程目录中的res目录下,包含了animator(属性动画资源)、anim(补间动画资源)、color(对象颜色状态选择资源)、drawable(xml或Bitmap文件的图像资源)、layout(布局文件资源)、menu(程序菜单资源)、mipmap(图标资源,推荐阅读:drawable与mipmap的区别)、raw(不被编译成二进制文件的资源,注意和assets资源的区别,推荐阅读:assets和raw的区别)、values(6种不同的值:数组arrays.xml、颜色值colors.xml、尺寸dimens.xml、字符串strings.xml和样式值styles.xml)、xml(描述应用程序配置信息的资源)。
如下截图展示了R.java的内容,其中包含了各种静态内部类,分别对应了某种资源的类型。

R.java结构图
以R.string类为例,其中展示了字符串名称对应的id值,就是对应在res/values文件夹下,string字符串资源。

R.string结构图
推荐阅读:apk打包安装过程
2、aidl生成跨进程通信的java文件
- 工具:aidl(Android Interface Definition Language安卓接口定义语言)
- 工具路径:sdkpath/build-tools/版本号/aidl.exe
- 输入:aidl后缀的文件,位于工程项目src/main/aidl目录下
- 输出:可用于进程间通信的C/S端java代码,位于build/generated/source/aidl

工程项目中的aidl原始文件

aidl工具处理后生成的java文件
3、Java编译源码
- 工具:javac.exe
- 工具路径:jdk/bin/javac.exe
- 输入:java source文件夹、aapt中生成的R.java文件、aidl生成的java文件、BuildConfig.java文件
- 输出:对于gradle编译,生成的class文件保存在build/intermediates/classes里

BuildConfig.java和R.java文件
