Android SDK 构建工具介绍

前面的小节我们学习了 Android SDK 工具。本小节我们学习 Android SDK 构建工具。

1. 概述

Android SDK 构建工具位于以下位置:android_sdk/build-tools/version/

Android SDK 构建工具用于构建 Android 应用。这里的工具大多数都是由编译工具调用的,而不是供我们使用的。不过,以下命令行工具可能很有用:

  • aapt2
    解析 Android 资源,为其编制索引,然后将其编译为针对 Android 平台优化的二进制格式,最后将编译后的资源打包到单个输出中。

  • apksigner
    为 APK 签名,并检查签名能否在给定 APK 支持的所有平台版本上成功通过验证。

  • zipalign
    确保所有未压缩数据的开头均相对于文件开头部分执行特定的对齐,从而优化 APK 文件。

2. aapt2

AAPT2(Android 资源打包工具)是一个构建工具,Android Studio 和 Android Gradle 插件使用它来编译和打包应用的资源。AAPT2 会解析资源、为资源编制索引,并将资源编译为针对 Android 平台进行过优化的二进制格式。

AAPT2 支持通过启用增量编译实现更快的资源编译。这是通过将资源处理拆分为两个步骤来实现的:

  • 编译:将资源文件编译为二进制格式。

  • 链接:合并所有已编译的文件并将它们打包到一个软件包中

2.1 编译

  • 编译语法
aapt2 compile path-to-input-files [options] -o output-directory/

在以下示例中,AAPT2 分别编译了名为 strings.xml 和 myImage.png 的资源文件:

aapt2 compile project_root/module_root/src/main/res/values-en/
strings.xml -o compiled/
aapt2 compile project_root/module_root/src/main/res/drawable
/myImage.png -o compiled/

如上表中所示,输出文件的名称取决于输入文件的名称及其父目录(资源类型和配置)的名称。对于以 strings.xml 作为输入的上述示例,aapt2 会自动将输出文件命名为 values-en_strings.arsc.flat。另一方面,存储在 drawable 目录中的已编译可绘制对象文件的文件名将为 drawable_img.png.flat。

  • 编译选项
命令选项 说明
-o 指定已编译资源的输出路径。
–dir 指定要在其中搜索资源的目录。
–pseudo-localize 生成默认字符串的伪本地化版本,如 en-XA 和 en-XB。
–no-crunch 停用 PNG 处理。
–legacy 将使用早期版本的 AAPT 时允许的错误视为警告。
-v 启用详细日志记录。

2.2 链接

  • 链接语法
aapt2 link path-to-input-files [options] -o
outputdirectory/outputfilename.apk --manifest AndroidManifest.xml

在以下示例中,AAPT2 将两个中间文件(drawable_Image.flat 和 values_values.arsc.flat)与 AndroidManifest.xml 文件进行了合并。AAPT2 会根据 android.jar 文件链接结果,该文件中包含了 android 软件包中定义的资源:

aapt2 link -o output.apk
 -I android_sdk/platforms/android_version/android.jar
    compiled/res/values_values.arsc.flat
    compiled/res/drawable_Image.flat --manifest /path/to/AndroidManifest.xml -v
  • 链接选项
命令选项 说明
-o 指定链接的资源 APK 的输出路径。
–manifest 指定要构建的 Android 清单文件的路径。
-I 提供平台的 android.jar 或其他 APK(如 framework-res.apk)的路径。
-A 指定要包含在 APK 中的资产目录。
-R 传递要链接的单个 .flat 文件,使用 overlay 语义。
–package-id 指定要用于应用的软件包 ID。
–allow-reserved-package-id 允许使用保留的软件包 ID。
–java 指定要在其中生成 R.java 的目录。
–proguard 为 ProGuard 规则生成输出文件。
–proguard-conditional-keep-rules 为主 dex 的 ProGuard 规则生成输出文件。
–no-auto-version 停用自动样式和布局 SDK 版本控制。
–no-version-vectors 停用矢量可绘制对象的自动版本控制。
–no-version-transitions 停用转换资源的自动版本控制。
–no-resource-deduping 禁止在兼容配置中自动删除具有相同值的重复资源。
–enable-sparse-encoding 允许使用二进制搜索树对稀疏条目进行编码。
-z 要求对标记为“建议”的字符串进行本地化。
-c 提供以英文逗号分隔的配置列表。
–preferred-density 允许 AAPT2 选择最相符的密度并删除其他所有密度。
–output-to-dir 将 APK 内容输出到 -o 指定的目录中。
–min-sdk-version 设置要用于 AndroidManifest.xml 的默认最低 SDK 版本。
–target-sdk-version 设置要用于 AndroidManifest.xml 的默认目标 SDK 版本。
–version-code 指定没有版本代码时要注入 AndroidManifest.xml 中的版本代码。
–compile-sdk-version-name 指定没有版本名称时要注入 AndroidManifest.xml 中的版本名称。
–proto-format 以 Protobuf 格式生成已编译的资源。
–non-final-ids 使用非最终资源 ID 生成 R.java。
–emit-ids 在给定的路径上生成一个文件,该文件包含资源类型的名称及其 ID 映射的列表。
–stable-ids 使用通过 --emit-ids 生成的文件,该文件包含资源类型的名称以及为其分配的 ID 的列表。
–custom-package 指定要在其下生成 R.java 的自定义 Java 软件包。
–extra-packages 生成相同的 R.java 文件,但软件包名称不同。
–add-javadoc-annotation 向已生成的所有 Java 类添加 JavaDoc 注释。
–output-text-symbols 生成包含指定文件中 R 类的资源符号的文本文件。
–auto-add-overlay 允许在叠加层中添加新资源。
–rename-manifest-package 重命名 AndroidManifest.xml 中的软件包。
–rename-instrumentation-target-package 更改插桩的目标软件包的名称。
-0 指定不想压缩的文件的扩展名。
–split 根据一组配置拆分资源,以生成另一个版本的 APK。
-v 可提高输出的详细程度。

3. apksigner

3.1 语法

  • 为 APK 签名
apksigner sign --ks keystore.jks |
  --key key.pk8 --cert cert.x509.pem
  [signer_options] app-name.apk

在使用 apksigner 工具为 APK 签名时,必须提供签名者的私钥和证书。我们可以通过两种不同的方式添加此信息:

  1. 使用 –ks 选项指定密钥库文件。

  2. 使用 –key–cert 选项分别指定私钥文件和证书文件。私钥文件必须使用 PKCS #8 格式,证书文件必须使用 X.509 格式。

通常情况下,我们只会使用一个签名者为 APK 签名。如果我们需要使用多个签名者为 APK 签名,请使用 –next-signer 选项将要应用于每个签名者的常规选项集分隔开:

apksigner sign [signer_1_options] --next-signer [signer_2_options] app-name.apk

以下示例使用 release.jks(密钥库中唯一的密钥)为 APK 签名:

apksigner sign --ks release.jks app.apk

以下示例使用私钥和证书(存储为不同的文件)为 APK 签名:

apksigner sign --key release.pk8 --cert release.x509.pem app.apk

以下示例使用两个密钥为 APK 签名:

apksigner sign --ks first-release-key.jks --next-signer --ks second-release-key.jks app.apk
  • 验证 APK 签名
apksigner verify [options] app-name.apk

以下示例检查 APK 的签名是否可在 APK 支持的所有 Android 平台上被确认为有效:

apksigner verify app.apk

以下示例检查 APK 的签名是否可在 Android 4.0.3(API 级别 15)及更高版本上被确认为有效:

apksigner verify --min-sdk-version 15 app.apk
  • 轮替签名密钥
apksigner rotate --in /path/to/existing/lineage 
  --out /path/to/new/file 
  --old-signer --ks old-signer-jks 
  --new-signer --ks new-signer-jks

以下示例启用支持密钥轮替的签名证书沿袭:

apksigner rotate --out /path/to/new/file --old-signer 
    --ks release.jks --new-signer --ks release2.jks

以下示例再次轮替我们的签名密钥:

apksigner rotate --in /path/to/existing/lineage 
  --out /path/to/new/file --old-signer --ks release2.jks 
  --new-signer --ks release3.jks

3.2 签名命令选项

命令选项 说明
–out 将要保存已签名 APK 的位置。
–min-sdk-version 用来确认 APK 签名将通过验证的最低 Android 框架 API 级别。
–max-sdk-version 用来确认 APK 签名将通过验证的最高 Android 框架 API 级别。
–v1-signing-enabled 确定是否会使用基于 JAR 的传统签名方案为给定的 APK 软件包签名。
–v2-signing-enabled 确定是否会使用 APK 签名方案 v2 为给定的 APK 软件包签名。
–v3-signing-enabled 确定是否会使用 APK 签名方案 v3 为给定的 APK 软件包签名。
–v4-signing-enabled 确定是否会使用 APK 签名方案 v4 为给定的 APK 软件包签名。
–v4-no-merkle-tree 使用此标志时,不会嵌入完整的 Merkle 树。
–verbose 使用详细输出模式。
–ks 签名者的私钥和证书链包含在给定的基于 Java 的密钥库文件中。
–ks-key-alias 签名者在密钥库中的私钥和证书数据的别名的名称。
–ks-pass 包含签名者私钥和证书的密钥库的密码。
pass:密码与 apksigner sign 命令的其余部分一起提供。
env:密码存储在给定的环境变量中。
file:密码作为单行存储在给定文件中。
stdin:密码作为单行在标准输入流中提供。这是 --ks-pass 的默认行为。
–ks-type 与包含签名者的私钥和证书的密钥库关联的类型或算法。
–ks-provider-name 请求签名者的密钥库实现时使用的 JCA 提供程序的名称。
–ks-provider-class 请求签名者的密钥库实现时使用的 JCA 提供程序的完全限定类名。
–ks-provider-arg 要作为 JCA 提供程序类的构造函数的参数传入的字符串值。
–key 包含签名者私钥的文件的名称。
–key-pass 签名者私钥的密码。
pass:密码与 apksigner sign 命令的其余部分一起提供。
env:密码存储在给定的环境变量中。
file:密码作为单行存储在给定文件中。
stdin:密码作为单行在标准输入流中提供。这是 --key-pass 的默认行为。
–cert 包含签名者证书链的文件的名称。

3.3 验证命令选项

命令选项 说明
–print-certs 显示有关 APK 签名证书的信息。
–min-sdk-version 用来确认 APK 签名将通过验证的最低 Android 框架 API 级别。
–max-sdk-version 用来确认 APK 签名将通过验证的最高 Android 框架 API 级别。
–verbose 使用详细输出模式。
-Werr 将警告视为错误。

4. zipalign

zipalign 是一种归档对齐工具,可对 Android 应用 (APK) 文件提供重要的优化。其目的是要确保所有未压缩数据的开头均相对于文件开头部分执行特定的对齐。具体来说,它会使 APK 中的所有未压缩数据(例如图片或原始文件)在 4 字节边界上对齐。这样做的好处是可以减少运行应用时消耗的 RAM 容量。

4.1 语法

要对齐 infile.apk 并将其保存为 outfile.apk,请运行以下命令:

zipalign [-f] [-v] <alignment> infile.apk outfile.apk

要确认 existing.apk 的对齐方式,请运行以下命令:

zipalign -c -v <alignment> existing.apk

alignment 是一个整数,用于定义字节对齐边界。此值必须始终为 4(可提供 32 位对齐),否则实际将不会执行任何操作。

标记:

  • -f:覆盖现有的 outfile.zip

  • -v:详细输出

  • -p:outfile.zip 应对 infile.zip 中的所有共享对象文件使用相同的页面对齐方式

  • -c:确认给定文件的对齐方式

5. 小结

本节课程我们主要学习了 Android SDK 构建工具。本节课程的重点如下:

  • 掌握如何使用 Android SDK 构建工具。