AAPT2(Android 资源打包工具)是 Android Studio 和 Android Gradle 插件用于编译和打包应用资源的构建工具。AAPT2 会解析、索引并将资源编译成针对 Android 平台优化的二进制格式。
Android Gradle 插件 3.0.0 及更高版本默认启用 AAPT2。您通常无需亲自调用 aapt2
。但是,如果您更喜欢使用终端和自己的构建系统而非 Android Studio,则可以从命令行使用 AAPT2。您还可以从命令行调试与 AAPT2 相关的构建错误。为此,请在 Android SDK Build Tools 26.0.2 及更高版本中找到 AAPT2 作为独立工具。
要从命令行下载 Android SDK Build Tools,请使用 sdkmanager
并运行以下命令
sdkmanager "build-tools;build-tools-version"
下载 SDK Build Tools 后,在 android_sdk/build-tools/version/
中找到 AAPT2。
由于 Android SDK Build Tools 的修订版本不经常发布,因此您的 SDK Build Tools 中包含的 AAPT2 版本可能不是最新版本。要获取最新版本的 AAPT2,请从 Google Maven 下载 AAPT2。
要在 Linux 或 Mac 上从命令行使用 AAPT2,请运行 aapt2
命令。在 Windows 上,运行 aapt2.exe
命令。
AAPT2 通过启用增量编译来支持更快的资源编译。为了实现增量编译,资源处理分为两个步骤
这种分离有助于提高增量构建的性能。例如,如果单个文件有更改,您只需重新编译该文件。
从 Google Maven 下载 AAPT2
要获取未捆绑在构建工具中的最新版 AAPT2,请按如下方式从 Google 的 Maven 代码库下载 AAPT2
- 在代码库索引中,导航到 com.android.tools.build > aapt2。
- 复制最新版 AAPT2 的名称。
将您复制的版本名称插入到以下网址中,并指定您的目标操作系统:https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/ aapt2-version/aapt2-aapt2-version- [windows | linux | osx].jar
例如,要下载适用于 Windows 的版本 3.2.0-alpha18-4804415,请使用:https://dl.google.com/dl/android/maven2/com/android/tools/build/aapt2/ 3.2.0-alpha18-4804415/aapt2-3.2.0-alpha18-4804415-windows.jar
在浏览器中导航到该网址。AAPT2 将很快开始下载。
解压缩您刚刚下载的 JAR 文件。
JAR 文件应包含一个
aapt2
可执行文件以及可执行文件所依赖的一些库。
编译
AAPT2 支持编译所有Android 资源类型,例如可绘制资源和 XML 文件。当您调用 AAPT2 进行编译时,每次调用都传递单个资源文件作为输入。然后 AAPT2 解析该文件并生成一个带有 .flat
扩展名的中间二进制文件。
当传递整个目录时,即使只有一个资源发生更改,AAPT2 也会重新编译目录中的所有文件。尽管您可以使用 --dir
标志将包含多个资源文件的资源目录传递给 AAPT2,但这样做您不会获得增量资源编译的好处。
输出文件类型可能因您为编译提供的输入而异,如下表所示
表 1. 编译的输入和输出文件类型
输入 | 输出 |
---|---|
位于 res/values/ 目录中的 XML 资源文件,例如字符串和样式 |
资源表,扩展名为 *.arsc.flat 。 |
所有其他资源文件。 |
此外,所有 PNG 文件默认都会被“紧缩”处理,并采用 |
AAPT2 输出的文件不是可执行文件,您稍后必须在链接阶段将这些二进制文件作为输入,以生成 APK。但是,生成的 APK 文件不是您可以立即部署到 Android 设备的可执行文件,因为它不包含 DEX 文件并且未签名。
编译语法
使用 compile
的一般语法如下
aapt2 compile path-to-input-files [options] -o output-directory/
在以下示例中,AAPT2 单独编译名为 values.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/
如表 1 所示,输出文件的名称取决于输入文件名及其父目录的名称。
对于以 strings.xml
文件作为输入的上例,aapt2
自动将输出文件命名为 values-en_strings.arsc.flat
。但是,存储在 drawable 目录中的已编译可绘制文件名为 drawable_img.png.flat
。
编译选项
您可以与 compile
命令一起使用多个选项,如表 2 所示
表 2. 编译命令选项
选项 | 描述 |
---|---|
-o 路径
|
指定已编译资源的输出路径。 这是一个必需的标志,因为您必须指定一个目录路径,AAPT2 可以在其中输出和存储已编译的资源。 |
--dir 目录
|
指定要扫描资源的目录。 尽管您可以使用此标志通过一个命令编译多个资源文件,但它会禁用增量编译的优势。因此,大型项目不应使用此标志。 |
--pseudo-localize
|
生成默认字符串的伪本地化版本,例如 en-XA 和 en-XB 。 |
--no-crunch
|
禁用 PNG 处理。
如果您已经处理过 PNG 文件,或者正在创建不需要减小文件大小的调试版本,请使用此选项。启用此选项可加快执行速度,但会增加输出文件大小。 |
--legacy
|
将使用早期版本的 AAPT 时允许出现的错误视为警告。
此标志应用于处理意外的编译时错误。要解决使用 AAPT2 时可能出现的已知行为更改,请阅读使用 AAPT2 时的行为更改。 |
-zip 文件
|
file 是一个 ZIP 文件,其中包含要扫描资源的 res 目录。 |
-output-text-symbols 文件
|
生成一个文本文件,其中包含指定资源符号 |
-preserve-visibility-of-styleables
|
如果指定,则对可样式化资源应用与所有其他资源相同的可见性规则。否则,所有可样式化资源都将公开。 |
-visibility [public|private|default|]
|
将已编译资源的可见性设置为指定级别。 |
-trace-folder 文件夹
|
生成一个 systrace JSON 跟踪片段到指定的 |
-source-path 路径
|
将已编译资源文件的源文件路径设置为 |
-h
|
显示工具帮助。 |
-v
|
启用详细日志记录。 |
链接
在链接阶段,AAPT2 合并编译阶段生成的所有中间文件,例如资源表、二进制 XML 文件和已处理的 PNG 文件,然后将这些文件打包到一个 APK 中。此外,在此阶段还可以生成其他辅助文件,例如 R.java
和 ProGuard 规则文件。但是,生成的 APK 不包含 DEX 字节码且未签名。您无法将此 APK 部署到设备。
如果您不使用 Android Gradle 插件来从命令行构建应用,则可以使用其他命令行工具,例如 d8 将 Java 字节码编译为 DEX 字节码,以及 apksigner 对 APK 进行签名。
链接语法
使用 link
的一般语法如下
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
链接选项
您可以与 link
命令一起使用以下选项
表 3. 链接命令选项
选项 | 描述 |
---|---|
-o 路径
|
指定链接资源 APK 的输出路径。 这是一个必需的标志,因为您必须指定用于保存链接资源的输出 APK 的路径。 |
--manifest 文件
|
指定要构建的 Android 清单文件的路径。 这是一个必需的标志,因为清单文件包含有关应用的重要信息,例如软件包名称和应用 ID。 |
-I
|
提供平台 android 命名空间的属性,则此标志是必需的。 |
-A 目录
|
指定要包含在 APK 中的 assets 目录。
您可以使用此目录存储原始的、未经处理的文件。要了解更多信息,请阅读访问原始文件。 |
-R 文件
|
使用 overlay 语义将单个 .flat 文件传递给 link ,而无需使用 <add-resource> 标记。
当您提供一个覆盖现有文件的资源文件时,将使用最后给定的冲突资源。 |
--package-id package-id
|
指定用于您应用的软件包 ID。
您指定的软件包 ID 必须大于或等于 0x7f,除非与 |
--allow-reserved-package-id
|
允许使用保留的软件包 ID。 保留的软件包 ID 是通常分配给共享库的 ID,范围从 0x02 到 0x7e(含)。通过使用 此选项仅应 Sdk 版本为 26 或更低的软件包。 |
--java 目录
|
指定生成 R.java 的目录。 |
--proguard proguard_options
|
为 ProGuard 规则生成输出文件。 |
--proguard-conditional-keep-rules
|
为主 DEX 的 ProGuard 规则生成输出文件。 |
--no-auto-version
|
禁用自动样式和布局 SDK 版本控制。 |
--no-version-vectors
|
禁用矢量可绘制资源的自动版本控制。仅在使用矢量可绘制库构建 APK 时使用此标志。 |
--no-version-transitions
|
禁用过渡资源的自动版本控制。仅在使用过渡支持库构建 APK 时使用此标志。 |
--no-resource-deduping
|
禁用具有相同值的资源在兼容配置间的自动去重。 |
--enable-sparse-encoding
|
启用使用二叉搜索树对稀疏条目进行编码。这对于优化 APK 大小很有用,但会牺牲资源检索性能。 |
-z
|
要求对标记为“建议”的字符串进行本地化。 |
-c 配置
|
提供逗号分隔的配置列表。
例如,如果您依赖于支持库(其中包含多种语言的翻译),则可以仅针对给定语言配置(例如英语或西班牙语)过滤资源。 您必须通过两位字母的 ISO 639-1 语言代码定义语言配置,后面可选择跟一个由小写字母“r”前缀的两位字母 ISO 3166-1-alpha-2 区域代码。例如,en-rUS。 |
--preferred-density 密度
|
允许 AAPT2 选择最接近的匹配密度并移除所有其他密度。
您的应用中可以使用多种像素密度限定符,例如 ldpi、hdpi 和 xhdpi。当您指定首选密度时,AAPT2 会在资源表中选择并存储最接近的匹配密度,并移除所有其他密度。 |
--output-to-dir
|
将 APK 内容输出到由 -o 指定的目录。
如果您在使用此标志时遇到任何错误,可以通过升级到 Android SDK Build Tools 28.0.0 或更高版本来解决。 |
--min-sdk-version min-sdk-version
|
设置用于 AndroidManifest.xml 的默认最低 SDK 版本。 |
--target-sdk-version target-sdk-version
|
设置用于 AndroidManifest.xml 的默认目标 SDK 版本。 |
--version-code version-code
|
指定要注入到 AndroidManifest.xml 中的版本代码(如果不存在)。 |
--version-name version-name
|
指定要注入到 AndroidManifest.xml 中的版本名称(如果不存在)。 |
--revision-code revision-code
|
指定要注入到 AndroidManifest.xml 文件中的修订代码(如果不存在)。 |
--replace-version
|
如果指定了 --version-code 、--version-name 或 --revision-code ,则这些值将替换清单中已有的任何值。默认情况下,如果清单已定义这些属性,则不会发生任何更改。 |
--compile-sdk-version-nacodeme compile-sdk-version-name
|
指定要注入到 AndroidManifest.xml 文件中的版本代码(如果不存在)。 |
--compile-sdk-version-name compile-sdk-version-name
|
指定要注入到 AndroidManifest.xml 文件中的版本名称(如果不存在)。 |
--proto-format
|
以 Protobuf 格式生成已编译的资源。 适合作为 |
--non-final-ids
|
生成带有非最终资源 ID 的 R.java 。在 kotlinc 或 javac 编译期间,不会内联应用代码中对 ID 的引用。 |
--emit-ids 路径
|
在给定路径处生成一个文件,其中包含资源类型名称及其 ID 映射列表。这适合与 --stable-ids 一起使用。 |
--stable-ids outputfilename.ext
|
使用 --emit-ids 生成的文件,其中包含资源类型名称及其分配的 ID 列表。
此选项允许在链接时即使删除或添加新资源,分配的 ID 也能保持稳定。 |
--custom-package package_name
|
指定自定义 Java 软件包,用于生成 R.java 。 |
--extra-packages package_name
|
生成相同的 R.java 文件,但具有不同的软件包名称。 |
--add-javadoc-annotation annotation
|
为所有生成的 Java 类添加 JavaDoc 注释。 |
--output-text-symbols 路径
|
在指定文件中生成一个文本文件,其中包含 R 类的资源符号。
您必须指定输出文件的路径。 |
--auto-add-overlay
|
允许在覆盖中添加新资源,而无需使用 <add-resource> 标签。 |
--rename-manifest-package manifest-package
|
重命名 AndroidManifest.xml 文件中的软件包。 |
--rename-instrumentation-target-package instrumentation- target-package
|
更改 instrumentation 的目标软件包名称。
此选项应与 |
-0 扩展名
|
指定您不想压缩的文件扩展名。 |
--split 路径:config[,config[..]]
|
根据一组配置拆分资源,以生成不同版本的 APK。
您必须指定输出 APK 的路径以及配置集。 |
--proguard-main-dex 文件
|
用于主 DEX 生成的 ProGuard 规则的输出文件。 |
--proguard-minimal-keep-rules
|
生成最小集合的 ProGuard keep 规则。 |
--no-resource-removal
|
禁用自动删除没有默认值的资源。仅在构建运行时资源覆盖包时使用此选项。 |
-x
|
指定使用软件包标识符 0x01 的旧版标志。 |
--product 产品列表
|
指定要保留的产品名称的逗号分隔列表。 |
--no-xml-namespaces
|
从 AndroidManifest.xml 文件和 res/* 中的 XML 二进制文件中删除 XML 命名空间前缀和 URI 信息。 |
--shared-lib
|
生成一个共享的 Android 运行时库。 |
--static-lib
|
生成一个静态 Android 库。 |
--no-static-lib-packages
|
将所有库资源合并到应用的软件包下。 |
--no-proguard-location-reference
|
防止 ProGuard 规则文件引用源文件。 |
--private-symbols package-name
|
package-name 指定生成私有符号的 R.java 时要使用的软件包名称。如果未指定,公共和私有符号将使用应用的软件包名称。 |
--override-styles-instead-of-overlaying
|
使 -R 资源中定义的样式替换以前的定义,而不是合并它们。 |
--rename-resources-package package-name
|
将资源表中的软件包重命名为 package-name。 |
--no-compress
|
不压缩任何资源。 |
--keep-raw-values
|
保留 XML 文件中的原始属性值。 |
--no-compress-regex regular-expression
|
不压缩与 regular-expression 匹配的扩展名。使用 $ 符号表示行尾。使用区分大小写的 ECMAScript 正则表达式语法。 |
--warn-manifest-validation
|
将清单验证错误视为警告。 |
--exclude-configs 限定符[,限定符[..]]
|
排除其配置包含指定限定符的资源的值。 |
--debug-mode
|
在清单的应用节点中插入 android:debuggable="true" ,使应用即使在生产设备上也可调试。 |
--strict-visibility
|
不允许具有不同可见性级别的叠加层。 |
--exclude-sources
|
在以 Protobuf 格式生成资源时,不序列化源文件信息。 |
--trace-folder 文件夹
|
生成 systrace JSON 跟踪片段到指定的 文件夹。 |
--merge-only
|
仅合并资源而不验证资源引用。此标志应仅与 --static-lib 标志一起使用。 |
-h
|
显示帮助菜单。 |
-v
|
启用更详细的输出。 |
转储
dump
用于打印使用 link
命令生成的 APK 的信息。
转储语法
使用 dump
的一般语法如下
aapt2 dump sub-command filename.apk [options]
以下示例打印指定 APK 的资源表中的内容
aapt2 dump resources output.apk
转储子命令
将以下子命令之一与 dump
命令一起指定
表 4. 转储子命令
子命令 | 描述 |
---|---|
apc
|
打印编译期间生成的 AAPT2 容器 (APC) 的内容。 |
badging
|
打印从 APK 清单中提取的信息。 |
configurations
|
打印 APK 中资源使用的每个配置。 |
overlayable
|
打印 APK 的可覆盖资源。 |
packagename
|
打印 APK 的软件包名称。 |
permissions
|
打印从 APK 清单中提取的权限。 |
strings
|
打印 APK 资源表字符串池的内容。 |
styleparents
|
打印 APK 中使用的样式的父级。 |
resources
|
打印 APK 资源表的内容。 |
xmlstrings
|
打印 APK 已编译 XML 中的字符串。 |
xmltree
|
打印 APK 已编译 XML 的树结构。 |
转储选项
将以下选项与 dump
一起使用
表 5. 转储选项
选项 | 描述 |
---|---|
--no-values
|
显示资源时抑制值的输出。 |
--file 文件
|
指定一个文件作为要从 APK 中转储的参数。 |
-v
|
增加输出的详细程度。 |
差异
使用 diff
比较两个 APK 并识别它们之间的任何差异。
差异语法
使用 diff
的一般语法如下
aapt2 diff first.apk second.apk
diff
命令没有选项。
优化
optimize
用于在合并的资源和 resources.arsc
打包到 APK 之前对其进行优化。此优化可将 APK 大小减小约 1-3%,具体取决于所使用的资源的大小和数量。
优化语法
使用 optimize
的一般语法如下
aapt2 optimize options file[,file[..]]
以下示例优化 input.apk
中的资源,并在 output.apk
中创建一个新的、优化的 APK。它用更紧凑的二叉搜索树替换了通常的平面表表示,从而在牺牲检索性能的情况下实现了更小的 APK
aapt2 optimize -o output.apk --enable-sparse-encoding input.apk
优化选项
您可以与 optimize
一起使用以下选项
表 6. 优化选项
选项 | 描述 |
---|---|
-o 路径
|
指定链接资源 APK 的输出路径。
这是一个必需的标志,因为您必须指定用于保存链接资源的输出 APK 的路径。 |
-d 目录
|
指定拆分输出目录的路径。 |
-x 路径
|
指定 XML 配置文件路径。 |
-p
|
打印多 APK 工件并退出。 |
--target-densities density[,density[..]]
|
指定 APK 优化的屏幕密度列表,以逗号分隔。将从 APK 中删除在给定密度设备上不会使用的所有资源。 |
--resources-config-path 路径
|
指定 格式:type/resource_name#[directive][,directive] |
-c 配置[,配置[..]]
|
指定要包含的配置的逗号分隔列表。默认是所有配置。 |
--split 路径:config[,config[..]]
|
根据一组配置拆分资源,以生成不同版本的 APK。
您必须指定输出 APK 的路径以及配置集。 |
--keep-artifacts artifact[,artifact[..]]
|
指定要保留的工件的逗号分隔列表。如果未指定,则保留所有工件。 |
--enable-sparse-encoding
|
启用使用二叉搜索树对稀疏条目进行编码。此选项对于优化 APK 大小很有用,但会牺牲资源检索性能。 |
--collapse-resource-names
|
将资源名称在键字符串池中合并为单个值。可以使用 --resources-config-path 指定的文件中的 no_collapse 指令来豁免资源。 |
--shorten-resource-paths
|
缩短 APK 内资源的路径。 |
--resource-path-shortening-map 路径
|
指定输出旧资源路径到缩短路径映射的路径。 |
-v
|
增加输出的详细程度。 |
-h
|
显示工具帮助。 |
转换
默认情况下,AAPT compile
命令将资源编译成适用于 APK 的二进制格式。也可以通过指定 --proto-format
来指定适用于 AAB 的 protobuf 格式。convert
命令在两种格式之间转换 APK。
转换语法
convert
的一般语法如下
aapt2 convert -o output-file options file[,file[..]]
以下示例转换 input.apk
中的资源,并在 output.apk
中创建一个新的 APK,其中包含 protobuf 格式的资源。它用更紧凑的二叉搜索树替换了通常的平面表表示,从而在牺牲检索性能的情况下实现了更小的 APK
aapt2 convert -o output.apk --output-format proto --enable-sparse-encoding input.apk
转换选项
将以下选项与 convert
一起使用
表 7. 转换选项
选项 | 描述 |
---|---|
-o 路径
|
指定链接资源 APK 的输出路径。 这是一个必需的标志,因为您必须指定用于保存链接资源的输出 APK 的路径。 |
--output-format [proto|binary]
|
输出格式。接受的值为 proto 和 binary 。如果未设置,则默认为 binary 。 |
--enable-sparse-encoding
|
启用使用二叉搜索树对稀疏条目进行编码。此选项对于优化 APK 大小很有用,但会牺牲资源检索性能。 |
--keep-raw-values
|
保留 XML 文件中的原始属性值。 |
-v
|
增加输出的详细程度。 |
-h
|
显示工具帮助。 |
守护进程模式
AAPT 版本 2.19 引入了用于发出命令的守护进程模式。守护进程模式允许您在单个 AAPT 会话中输入多个命令。
守护进程语法
使用以下命令启动守护进程模式
aapt2 daemon
守护进程模式运行后,您可以输入命令。命令的每个参数必须在单独的行上,命令末尾有一个空行。通过键入 Control+D 退出守护进程模式。
考虑以下单独的 compile
命令
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/
这些命令可以在守护进程模式下输入为
aapt2 daemon Ready compile project_root/module_root/src/main/res/values-en/strings.xml -o compiled/ Done compile project_root/module_root/src/main/res/drawable/myImage.png -o compiled/ Done ^D Exiting daemon
守护进程模式选项
守护进程模式的唯一选项是 --trace-folder 文件夹
,它会将 systrace
JSON 跟踪片段生成到指定的 文件夹。
版本
使用 version
命令确定您正在使用的 AAPT2 版本
aapt2 version Android Asset Packaging Tool (aapt) 2.19-8678579
使用 AAPT2 时的行为更改
在 AAPT2 之前,AAPT 是 Android 资产打包工具的默认版本,现已弃用。尽管 AAPT2 应立即与旧项目一起使用,但本节介绍了一些您应该注意的行为更改。
Android 清单中的元素层次结构
在 AAPT 的早期版本中,嵌套在 AndroidManifest.xml
文件中不正确节点中的元素要么被忽略,要么导致警告。例如,考虑以下示例
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myname.myapplication"> <application ... <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <action android:name="android.intent.action.CUSTOM" /> </activity> </application> </manifest>
早期版本的 AAPT 只会简单地忽略错位的 <action>
标签。
使用 AAPT2,您会收到以下错误
AndroidManifest.xml:15: error: unknown element <action> found.
要解决此问题,请确保您的清单元素正确嵌套。有关更多信息,请阅读应用清单概览。
资源的声明
您不能再从 name
属性中指示资源的类型。以下示例错误地声明了一个 attr
资源项
<style name="childStyle" parent="parentStyle"> <item name="attr/my_attr">@color/pink</item> </style>
以这种方式声明资源类型会导致以下构建错误
Error: style attribute 'attr/attr/my_attr (aka my.package:attr/attr/my_attr)' not found.
要解决此错误,请使用 type="attr"
显式声明类型
<style name="childStyle" parent="parentStyle"> <item type="attr" name="my_attr">@color/pink</item> </style>
此外,在声明 <style>
元素时,其父级也必须是样式资源类型。否则,您会收到类似以下内容的错误
Error: (...) invalid resource type 'attr' for parent of style
资源引用符号 @ 的不正确使用
当您省略或错误放置资源引用符号 (@
) 时,AAPT2 会抛出构建错误。例如,如果您在指定样式属性时省略该符号
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> ... <!-- Note the missing '@' symbol when specifying the resource type. --> <item name="colorPrimary">color/colorPrimary</item> </style>
构建模块时,AAPT2 会抛出以下构建错误
ERROR: expected color but got (raw string) color/colorPrimary
此外,如果您在访问 android
命名空间中的资源时错误地包含该符号
... <!-- When referencing resources from the 'android' namespace, omit the '@' symbol. --> <item name="@android:windowEnterAnimation"/>
构建模块时,AAPT2 会抛出以下构建错误
Error: style attribute '@android:attr/windowEnterAnimation' not found
库配置不正确
如果您的应用依赖于使用旧版本 Android SDK 构建工具构建的第三方库,则您的应用可能会在运行时崩溃而不会显示任何错误或警告。发生此崩溃的原因可能是:在库创建期间,R.java
字段被声明为 final
。结果是,所有资源 ID 都内联在库的类中。
AAPT2 在构建应用时依赖于能够重新分配 ID 给库资源。如果库假定 ID 是 final
并在库 DEX 中内联它们,则会出现运行时不匹配。
要解决此错误,请联系库作者,使用最新版本的 Android SDK Build Tools 重新构建库,并重新发布库。