如何在APK构建过程中自动压缩res/raw与assets中的XML、JSON文件?
自动压缩res/raw和assets中的XML/JSON文件
当然可以在构建流程里自动搞定这个压缩需求!AGP、R8这些默认确实不会处理XML、JSON这类文本资源,但咱们可以通过自定义Gradle任务或者借助工具库把这个流程自动化,完全不用手动折腾啦。
我给你两种实用方案,你可以根据自己的需求选:
方案一:纯Gradle自定义任务(无额外依赖)
这个方案会在构建的资源处理阶段,自动遍历res/raw和assets下的XML、JSON文件,移除注释、冗余空白这类无用内容,同时保证文件格式合法。
步骤1:在app模块的build.gradle里加任务配置
把这段代码贴到你的build.gradle(Groovy语法)里:
// 压缩JSON文件的任务 task minifyJsonFiles(type: Copy) { // 匹配assets和res/raw下所有.json文件 from 'src/main/assets', 'src/main/res/raw' include '**/*.json' // 输出到临时目录,不修改源文件 def tempDir = file("$buildDir/tmp/minifiedJson") into tempDir // 处理每个JSON:移除注释和冗余空白 eachFile { file -> filter { line -> // 去掉单行注释 !line.trim().startsWith('//') && // 去掉多行注释的首尾标记 !line.trim().startsWith('/*') && !line.trim().endsWith('*/') } // 移除多余空白字符(保留必要结构) filter { it.replaceAll(/\s+/, ' ') } } } // 压缩XML文件的任务 task minifyXmlFiles(type: Copy) { from 'src/main/assets', 'src/main/res/raw' include '**/*.xml' def tempDir = file("$buildDir/tmp/minifiedXml") into tempDir // 移除XML注释和标签间的空白 eachFile { file -> filter(StripXmlComments) filter { it.replaceAll(/>\s+</, '><') } } } // 自定义过滤器:移除XML注释 class StripXmlComments extends FilterReader { StripXmlComments(Reader in) { super(in) } String readLine() { String line = super.readLine() while (line != null) { def stripped = line.replaceAll(/<!--.*?-->/, '').trim() if (!stripped.isEmpty()) { return stripped } line = super.readLine() } return null } } // 让压缩任务在构建前执行 preBuild.dependsOn minifyJsonFiles, minifyXmlFiles // 让资源合并任务使用压缩后的文件 android.sourceSets.main.res.srcDirs += minifyXmlFiles.outputs.files.asFileTree android.sourceSets.main.assets.srcDirs += minifyJsonFiles.outputs.files.asFileTree
步骤2:保留你的原有release配置
你现在的release配置已经开了混淆和资源收缩,和这个压缩任务完全不冲突,继续用就行:
release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' shrinkResources true }
方案二:用专业工具库压缩(更可靠彻底)
如果需要更专业的压缩(比如JSON语法优化、XML冗余节点清理),可以用专门的工具库,比如Jackson处理JSON,XmlUnit处理XML。这里以Jackson为例:
步骤1:添加依赖到build.gradle
buildscript { dependencies { classpath 'com.fasterxml.jackson.core:jackson-databind:2.15.2' } }
步骤2:修改JSON压缩任务
import com.fasterxml.jackson.databind.ObjectMapper task minifyJsonFiles(type: Copy) { from 'src/main/assets', 'src/main/res/raw' include '**/*.json' def tempDir = file("$buildDir/tmp/minifiedJson") into tempDir eachFile { file -> filter { content -> ObjectMapper mapper = new ObjectMapper() // 读取JSON并输出为最小化格式,保证语法绝对正确 mapper.writeValueAsString(mapper.readTree(content)) } } }
这种方式比正则替换更可靠,能确保压缩后的JSON完全符合语法规范,不会出现解析问题。
验证效果
配置好后,执行./gradlew assembleRelease,然后用APK Analyzer打开生成的APK,看看res/raw和assets下的文件体积,应该和你手动压缩后的效果一致。
⚠️ 注意事项:
- 如果有些文件需要保留注释或格式(比如应用要读取注释的配置文件),可以修改
include规则,用exclude把这些文件排除在外。 - 先跑
./gradlew assembleDebug测试一下,确保压缩后的文件能被应用正常读取,避免格式错误导致崩溃。
内容的提问来源于stack exchange,提问作者Maksim Turaev




