如何在Android项目中改变gradle中的proguard映射文件名

我有基于gradleandroid项目,我想要更改mapping.txt文件名称生成后为我的构build。 如何做呢?

UPD

如何在build.gradle中完成? 由于我有访问我的口味和其他僵硬,我想创build基于风味/build立变种版本的映射文件名。

Solutions Collecting From Web of "如何在Android项目中改变gradle中的proguard映射文件名"

更简单的解决scheme

applicationVariants.all { variant -> if (variant.getBuildType().isMinifyEnabled()) { variant.assemble.doLast { copy { from variant.mappingFile into "${rootDir}/proguardTools" rename { String fileName -> "mapping-${variant.name}.txt" } } } } } 

在你的proguard-rules.pro文件中使用这个命令:

 -printmapping path/to/your/file/file_name.txt 

该文件将用file_name.txt名称部分写入{root}/path/to/your/file file_name.txt

如果你想为不同的风格有不同的设置,你可以为它们定义许多proguard规则

我发现了一个更多的想法,但我不确定这是否正确。

你可以定义你的道路风味:

 productFlavors { test1 { applicationId "com.android.application.test" project.ext."${name}Path" = 'path/one/mapp.txt' } test2 { project.ext."${name}Path" = 'path/two/mapp.txt' } } 

接下来,您可以在$asseble{variant.name.capitalize()}任务之前定义新任务,如下所示:

 android.applicationVariants.all { variant -> def envFlavor = variant.productFlavors.get(0).name def modifyProguardPath = tasks.create(name: "modifyProguardFor${variant.name.capitalize()}", type: Exec) { def pathToMap = project."${envFlavor}Test1" doFirst { println "==== Edit start: $pathToMap ====" } doLast { println "==== Edit end: $pathToMap ====" } executable "${rootDir}/utils/test.bash" args pathToMap } project.tasks["assemble${variant.name.capitalize()}"].dependsOn(modifyProguardPath); } 

并在脚本${root}/utils/test.bash – 你可以修改proguard-rules.pro

但我认为存在更好的解决scheme。

由于上次更新variant.mappingFile不再可用。 (我使用ProGuard 4.7,AndroidStudio 2.0)

这是我的build.gradle文件(的一部分):

 import java.util.regex.Matcher import java.util.regex.Pattern def getCurrentFlavor() { Gradle gradle = getGradle() String tskReqStr = gradle.getStartParameter().getTaskRequests().toString() Pattern pattern; if( tskReqStr.contains( "assemble" ) ) pattern = Pattern.compile("assemble(\\w+)(Release|Debug)") else pattern = Pattern.compile("generate(\\w+)(Release|Debug)") Matcher matcher = pattern.matcher( tskReqStr ) if( matcher.find() ) return matcher.group(1).toLowerCase() else { println "NO MATCH FOUND" return ""; } } buildTypes { release { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' minifyEnabled true applicationVariants.all { variant -> variant.outputs.each { output -> output.outputFile = new File(output.outputFile.parent, "${variant.name}_v${variant.versionName}.apk") } def mappingFile = "${rootDir}\\app\\build\\outputs\\mapping\\${getCurrentFlavor()}\\release\\mapping.txt" println("mappingFile: ${mappingFile}") if (variant.getBuildType().isMinifyEnabled()) { variant.assemble.doLast { copy { from "${mappingFile}" into "${rootDir}" rename { String fileName -> "mapping-${variant.name}.txt" } } } } } } debug { minifyEnabled false useProguard false applicationVariants.all { variant -> variant.outputs.each { output -> output.outputFile = new File(output.outputFile.parent, "${variant.name}_v${variant.versionName}.apk") } } } } 

谢谢Sergii Pechenizkyi帮助我find了这个好的解决scheme。

为了实现对每种风味的proguard映射文件的复制,我们可以创build“根”任务copyProguardMappingTask和每个风味的dynamic任务的数量

 def copyProguardMappingTask = project.tasks.create("copyProguardMapping") applicationVariants.all { variant -> variant.outputs.each { output -> ... if (variant.getBuildType().isMinifyEnabled()) { def copyProguardMappingVariantTask = project.tasks.create("copyProguardMapping${variant.name.capitalize()}", Copy) def fromPath = variant.mappingFile; def intoPath = output.outputFile.parent; copyProguardMappingVariantTask.from(fromPath) copyProguardMappingVariantTask.into(intoPath) copyProguardMappingVariantTask.rename('mapping.txt', "mapping-${variant.name}.txt") copyProguardMappingVariantTask.mustRunAfter variant.assemble copyProguardMappingTask.dependsOn copyProguardMappingVariantTask } } } 

之后我们应该在组装我们的项目后执行这个任务。 我用jenkins和我的任务选项看起来像

 gradle clean assembleProjectName copyProguardMapping 

它像一个魅力。

所有这些答案使用副本重命名文件。 我不想移动文件,但我只是想改变它的名字,记住构buildtypes和风味。

我以自己的其他海报的代码为基础,改变了一下。 由于Minify可能是假的,而仍然使用proguard,我只是检查文件是否存在。

以下代码完成这一点。

 android { applicationVariants.all { variant -> variant.assemble.doLast { def mappingFolderUrl = "${project.buildDir.path}/outputs/mapping/" if (variant.buildType.name) { mappingFolderUrl += variant.buildType.name + "/" } if (variant.flavorName) { mappingFolderUrl += variant.flavorName + "/" } def mappingFileUrl = mappingFolderUrl + "mapping.txt" logger.lifecycle("mappingFile path: ${mappingFileUrl}") File mappingFile = file(mappingFileUrl) if (mappingFile.exists()) { def newFileName = mappingFolderUrl + "mapping-${variant.name}.txt" mappingFile.renameTo(newFileName) } } } } 

注意

你也可以使用这段代码来移动文件。

.renameTo()方法需要一个完整的path,如果你改变path,我会假设你有效地将文件移动到另一个地方。

上面Pinhassi的解决scheme效果很好,符合最新的Gradle变化。 有几件事我不得不改变:

  1. 模块名称是硬编码(“app”),这是不理想的,因为在很多情况下(包括我的),这是不正确的。 dynamic检测模块名称更好。
  2. 映射文件也只有通过向后转义斜杠(“\”)符合Windows文件系统。 如果您使用Linux或Mac等* NIX系统,则需要使用前向非转义斜杠(“/”)replace
  3. 改变了.apk文件的重命名,以包括项目名称,并在最后添加了date/时间戳。

这是完成的代码:

 import java.util.regex.Matcher import java.util.regex.Pattern buildTypes { release { debuggable false minifyEnabled true proguardFiles 'proguard.cfg' // Rename the apk file and copy the ProGuard mapping file to the root of the project applicationVariants.all { variant -> if (variant.getBuildType().name.equals("release")) { def formattedDate = new Date().format('yyyyMMddHHmmss') def projectName = "" variant.outputs.each { output -> def fullName = output.outputFile.name projectName = fullName.substring(0, fullName.indexOf('-')) // ${variant.name} has the value of "paidRelease" output.outputFile = new File((String) output.outputFile.parent, (String) output.outputFile.name.replace(".apk", "-v${variant.versionName}-${formattedDate}.apk")) } def mappingFile = "${rootDir}/${projectName}/build/outputs/mapping/${getCurrentFlavor()}/release/mapping.txt" println("mappingFile: ${mappingFile}") if (variant.getBuildType().isMinifyEnabled()) { variant.assemble.doLast { copy { from "${mappingFile}" into "${rootDir}" rename { String fileName -> "mapping-${variant.name}.txt" } } } } } } } debug { debuggable true } } def getCurrentFlavor() { Gradle gradle = getGradle() String tskReqStr = gradle.getStartParameter().getTaskRequests().toString() Pattern pattern; if( tskReqStr.contains( "assemble" ) ) pattern = Pattern.compile("assemble(\\w+)(Release|Debug)") else pattern = Pattern.compile("generate(\\w+)(Release|Debug)") Matcher matcher = pattern.matcher( tskReqStr ) if( matcher.find() ) return matcher.group(1).toLowerCase() else { println "NO MATCH FOUND" return ""; } } 
 applicationVariants.all { variant -> variant.outputs.each { output -> if (variant.getBuildType().isMinifyEnabled()) { variant.assemble.doLast{ copy { from variant.mappingFile into "${rootDir}/mapping" rename { String fileName -> "mapping-${variant.name}-${new Date().format('yyyy_MM_dd')}.txt" } } } } } } 

这是igorpst的答案的变体,但重命名mapping.txt以匹配apk的名称完全包括应用程序版本的名称。 我已经将这个与代码结合起来,用这个答案中描述的版本号命名APK。 我不得不通过gradle源代码窥探$variant.baseName

 apply plugin: 'com.android.application' android { compileSdkVersion 21 buildToolsVersion "21.1.2" defaultConfig { applicationId "com.company.app" minSdkVersion 13 targetSdkVersion 21 versionCode 14 // increment with every release versionName '1.4.8' // change with every release archivesBaseName = "MyCompany-MyAppName-$versionName" } applicationVariants.all { variant -> if (variant.getBuildType().isMinifyEnabled()) { variant.assemble.doLast { (new File(variant.mappingFile.parent, "$archivesBaseName-$variant.baseName-mapping.txt")).delete(); variant.mappingFile.renameTo(variant.mappingFile.parent + "/$archivesBaseName-$variant.baseName-mapping.txt") } } } } 

之前的回答对我来说很好,直到Android 3.0 / Android Gradle Plugin 3.0弃用BuildType.isMinifyEnabled()

我开发了以下不使用弃用方法的解决scheme:

 applicationVariants.all { variant -> variant.assemble.doLast { if (variant.mappingFile != null && variant.mappingFile.exists()) { def mappingFilename = "$archivesBaseName-$variant.baseName-mapping.txt" (new File(variant.mappingFile.parent, mappingFilename)).delete() variant.mappingFile.renameTo(variant.mappingFile.parent + "/" + mappingFilename) } } }