作为一个安卓开发,如果你对安卓打包流程还不熟悉的话?不妨看看这篇文章。本文会带你深入了解安卓打包流程的各个细节。更重要的是,熟悉安卓打包流程会让你对apk瘦身、参数化构建、资源文件处理有更深的理解。
流程步骤
安卓apk打包的流程总的来说分为七个步骤,分别是:
aapt
打包资源文件、Manifest xml
布局文件、资源索引文件R.java
aidl
处理aidl文件,将aidl
文件编译成.java
文件javac
编译器将所有的.java
代码编译成.class
字节码dex
工具将所有的.class
字节码文件(包括第三方库)编译成.dex
文件(DVM和ArtVM识别的字节码文件)- 生成APK文件
- 签名。开发版签名(系统自带)和正式版签名(自主配置)
- 文件对齐(release版本开启)
谷歌官方曾给出过一张打包流程图:
从图中可以看出,整个流程包含上述的7个核心操作。我们平时在简单的执行run
任务时,其实AndroidStudio
默默的会为我们执行一遍打包流程(不考虑instantrun等)。
下面我们来针对每一步操作,进行深入的剖析。
第一步:AAPT打包资源文件
什么是aapt?
它是一款打包工具,安卓SDK目录下提供了它的可执行文件aapt
,具体目录位置为:sdk/build-tools/26.0.3/aapt
(请忽略sdk版本目录,在每个版本下面都会有),事实上高版本上会使用aapt2
。
我们使用它的命令行版本信息指令aapt version
来看下它的详情:
Android Asset Packaging Tool, v0.2-4420879
当然也可以看下aapt2
的信息,指令是:aapt2 version
Android Asset Packaging Tool (aapt) 2:19
通过输出信息可以知道,aapt也就是:安卓资源打包工具。
前面提到过,他是以可执行文件的形式提供的,那么我们接下来先看看它都有哪些指令。通过直接执行指令aapt
就可以看到。主要包括:
指令全称 | 缩写 | 指令作用 |
---|---|---|
list | l | 输出压缩文件的所有内容 |
dump | d | 打印对应资源文件或者apk的指定信息 |
package | p | 打包安卓资源,主要包括assets和resources |
remove | r | 从压缩文件中删除指定文件 |
add | a | 向压缩文件中添加指定文件 |
crunch | c | 对多个目录下的PNG文件进行预处理并存储到输出目录 |
singleCrunch | s | 对单个PNG文件进行预处理 |
version | v | 打印aap的版本信息 |
这些指令中,在打包安卓应用时,主要会使用到package
指令。我们下面来看看该指令的一些用法:
aapt p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \
[-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] \
[--debug-mode] [--min-sdk-version VAL] [--target-sdk-version VAL] \
[--app-version VAL] [--app-version-name TEXT] [--custom-package VAL] \
[--rename-manifest-package PACKAGE] \
[--rename-instrumentation-target-package PACKAGE] \
[--utf16] [--auto-add-overlay] \
[--max-res-version VAL] \
[-I base-package [-I base-package ...]] \
[-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \
[-D main-dex-class-list-file] \
[-S resource-sources [-S resource-sources ...]] \
[-F apk-file] [-J R-file-dir] \
[--product product1,product2,...] \
[-c CONFIGS] [--preferred-density DENSITY] \
[--split CONFIGS [--split CONFIGS]] \
[--feature-of package [--feature-after package]] \
[raw-files-dir [raw-files-dir] ...] \
[--output-text-symbols DIR]
在命令行窗口中,对于该命令有一个简短的描述:
Package the android resources. It will read assets and resources that are
supplied with the -M -A -S or raw-files-dir arguments. The -J -P -F and -R
options control which files are output.
该描述对于该命令的核心功能和核心参数都做了概括,打包命令支持很多参数,其中比较重要的几个在上述描述中已经说明。下面我们来看看这几个重要的参数的具体意义。
参数 | 说明 |
---|---|
-f | 覆盖现有的文件命令,加上后编译生成直接覆盖目前已经存在的R.java; |
-m | 使生成的包的目录放在-J参数指定的目录; |
-v | 详细输出,加上此命令会在控制台输出每一个资源文件信息,R.java生成后还有注释。 |
-M | AndroidManifest.xml的路径 |
-I | 指定的SDK版本中android.jar的路径 |
-A | assert文件夹的路径 |
-P | 指定的输出公共资源,可以指定一个文件 让资源ID输出到那上面 |
-D | 在多dex构建模式下,主构建dex的设计的类文件列表 |
-S | 指定资源目录 一般是 res |
-F | 指定把资源输出到 apk文件中 |
-J | 指定R.java输出的路径 |
–product | 指定想要选择的打包变体(product-flavor) |
–min-sdk-versopm VAL | 最小SDK版本 如是7以上 则默认编译资源的格式是 utf-8 |
–target-sdk-version VAL | 在androidMainfest中的目标编译SDK版本 |
–app-version VAL | 应用程序版本号 |
–app-version-name TEXT | 应该程序版本名字 |
–custom-package VAL | 生成R.java到一个不同的包 |
–rename-mainifest-package PACKAGE | 修改APK包名的选项 |
raw-file-dir | 附加打包进APK的文件 |
接下来,我们通过一个小例子来看下package
命令的使用和输出。
在作者本地有一个安卓项目。项目结构为:
我们通过以下命令来打包资源文件
aapt package -f -S /Users/lotty/android/lotty/component/src/main/res -M /Users/lotty/android/lotty/component/src/main/AndroidManifest.xml -A /Users/lotty/android/lotty/component/src/main/assets -I /Users/lotty/Library/Android/sdk/platforms/android-29/android.jar -m -J /Users/lotty/Desktop/out/ -v -F /Users/lotty/Desktop/out/test.apk
输出路径out
下面有两个文件:
解压输出文件test.apk的详情为:
对应的R.java为:
package com.github.component;
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int p1=0x7f020000;
public static final int p2=0x7f02000b;
public static final int ptr_header_down=0x7f020036;
public static final int ptr_header_loading=0x7f020037;
public static final int ptr_header_up=0x7f020038;
}
public static final class id {
public static final int content=0x7f050000;
public static final int ptr_header_content=0x7f050001;
public static final int ptr_header_hint=0x7f050002;
}