Android 项目中有一个功能,想从其它分支合并到主分支内,但是又希望把它用开关控制起来。这个需求往日里不算什么,但本次有所不同,因为这个功能还关联着有一组 assets 下的资源文件。这些文件加起来的体积不小,如果把相应的功能隐藏起来的话(例如在 build.gradle 中把会生成到 BuildConfig.java 的某个开关常量置为 false),希望构建时把关联的 assets 忽略掉,不打入包内以减小体积。
于是又向 grok 请教,而果然,还是它懂得多。给了几个方案,一个是分 sourceSet,这个不考虑;一个是安装后代码下载,也不考虑。另外还有俩。其一是,在构建脚本里写一个任务,而把所有的 assets 集中放到一个 source 目录中,当构建时,自动提前执行此任务,
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[crayon-6927be892d2fe297872660 inline="true" ]android { // 其他配置... // 动态设置 assets 目录 sourceSets { main { assets.srcDirs = ['src/main/assets_filtered'] } } } task filterAssets(type: Copy) { description 'Copy assets based on includeLargeAssets flag' from 'src/main/assets' into 'src/main/assets_filtered' // 根据开关过滤文件 if (!project.ext.includeLargeAssets) { exclude '**/*.largefile' // 假设大文件以 .largefile 结尾 } } // 确保在编译前执行过滤任务 preBuild.dependsOn filterAssets |
示例代码如上,一眼可以看懂,就不再多说了,这也不是当前需求的最佳解决办法。老夫看中的是最后一种(虽简单、但够用):使用 aaptOptions 块中的 ignoreAssetsPattern 语句定义过滤规则。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[crayon-6927be892d304646798183 inline="true" ]android { // 其他配置... // 定义一个开关(可以从命令行或默认值控制) ext { excludeLargeAssets = project.hasProperty('excludeLargeAssets') ? project.getProperty('excludeLargeAssets').toBoolean() : false } // 生成 BuildConfig 字段 buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' buildConfigField "boolean", "EXCLUDE_LARGE_ASSETS", "${excludeLargeAssets}" } debug { buildConfigField "boolean", "EXCLUDE_LARGE_ASSETS", "${excludeLargeAssets}" } } // 配置 aaptOptions,根据 excludeLargeAssets 动态设置 ignoreAssetsPattern aaptOptions { ignoreAssetsPattern excludeLargeAssets ? '!large/**' : '' } } |
ignoreAssetsPattern 的参数用的是 AAPT2 的通用模式匹配语法规则:
- 模式格式:由逗号(
,)分隔的多个规则,每个规则可以是:
- 忽略模式:以 ! 开头,表示忽略匹配的文件或目录。
- 包含模式:不以 ! 开头,表示只包含匹配的文件(但在 ignoreAssetsPattern 中很少使用,因为其主要用途是忽略)。
- 通配符:
- *:匹配文件名中的任意字符(不包括路径分隔符 /)。
- **:匹配任意字符,包括路径分隔符(用于匹配子目录)。
- ?:匹配单个字符。
- 示例:
- !large/**:忽略 assets/large/ 目录及其子目录下的所有文件。
- *.txt:理论上表示只包含 .txt 文件,但由于 ignoreAssetsPattern 主要用于忽略,这种用法不常见。
- !large/*.png,*.txt:忽略 assets/large/ 下的所有 .png 文件和 assets/ 根目录下的所有 .txt 文件。

永久链接
实操证明:指定 !large/** 这样的模式得不到预期结果,而要改成 !large。