You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动