Android ProGuard:如何修改mapping.txt的文件名与存储路径?
好问题!我之前也遇到过类似的困扰——Android Gradle插件默认会把mapping文件放在build目录里,确实容易被clean命令清空,而且直接在proguard-rules.pro里加-printmapping这类指令,有时候会被插件的默认配置覆盖,导致看起来没生效。下面给你两种可靠的解决方案:
方案一:通过Android Gradle插件配置(推荐)
Android Gradle插件提供了专门的配置项来指定mapping、seeds、usage文件的路径,这种方式不会被插件默认行为覆盖,更贴合Android构建流程。
Groovy 语法(build.gradle)
android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' // 自定义mapping文件的存储路径和名称 mappingFile = file("${project.rootDir}/foo/mapping.txt") // 配置seeds和usage文件的路径 proguardFile('proguard-rules.pro') { seedsFile = file("${project.rootDir}/foo/seeds.txt") usageFile = file("${project.rootDir}/foo/usage.txt") } } } } // 提前创建目标目录,避免生成文件时报错 task createMappingDir { doLast { file("${project.rootDir}/foo").mkdirs() } } // 让混淆任务依赖目录创建任务 tasks.whenTaskAdded { task -> if (task.name == 'minifyReleaseWithR8' || task.name == 'minifyReleaseWithProGuard') { task.dependsOn createMappingDir } }
Kotlin DSL 语法(build.gradle.kts)
android { buildTypes { release { isMinifyEnabled = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) // 自定义mapping文件路径 mappingFile = file("${project.rootDir}/foo/mapping.txt") // 配置seeds和usage文件路径 proguardFile("proguard-rules.pro") { seedsFile = file("${project.rootDir}/foo/seeds.txt") usageFile = file("${project.rootDir}/foo/usage.txt") } } } } // 提前创建目标目录 val createMappingDir by tasks.registering { doLast { file("${project.rootDir}/foo").mkdirs() } } // 绑定混淆任务与目录创建任务的依赖 tasks.whenTaskAdded { if (name == "minifyReleaseWithR8" || name == "minifyReleaseWithProGuard") { dependsOn(createMappingDir) } }
方案二:让ProGuard指令生效
如果你更倾向于用ProGuard原生指令,需要注意不能用相对路径(ProGuard的工作目录和你预期的可能不一致),并且要通过Gradle传递绝对路径变量给ProGuard:
android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' // 通过proguardOptions传递带绝对路径的指令 proguardOptions { "-printmapping ${project.rootDir}/foo/mapping.txt" "-printseeds ${project.rootDir}/foo/seeds.txt" "-printusage ${project.rootDir}/foo/usage.txt" } } } } // 同样需要提前创建目录 task createMappingDir { doLast { file("${project.rootDir}/foo").mkdirs() } } tasks.whenTaskAdded { task -> if (task.name == 'minifyReleaseWithR8' || task.name == 'minifyReleaseWithProGuard') { task.dependsOn createMappingDir } }
这种方式会让Gradle先解析${project.rootDir}为项目根目录的绝对路径,再传递给ProGuard,就能确保文件生成到你指定的位置了。
内容的提问来源于stack exchange,提问作者eastwater




