I have android project based on gradle and I want to change mapping.txt file name after it\'s generated for my build. How can it be done?
upd
How it can be d
Pinhassi's solution above works great and it is conforms to the latest Gradle changes. There are a couple of things though that I had to change:
Here is the finished code:
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 "";
}
}
Since the last update variant.mappingFile is not longer available. (I use ProGuard version 4.7, AndroidStudio 2.0)
This is (part of) my build.gradle file:
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")
}
}
}
}
As of today (May 2020) former solution, which uses variant.mappingFile
is not working anymore in new Android Gradle plugin (Android Studio) 3.6 and higher.
Instead variant.mappingFile
returns null
and following is displayed in the logs:
WARNING: API 'variant.getMappingFile()' is obsolete and has been replaced with 'variant.getMappingFileProvider()'.
I am sharing my working solution, which uses new api:
applicationVariants.all { variant ->
variant.assembleProvider.get().doLast {
def mappingFiles = variant.getMappingFileProvider().get().files
for (file in mappingFiles) {
if (file != null && file.exists()) {
def nameMatchingApkFile = "$archivesBaseName-$variant.baseName-$file.name"
def newMappingFile = new File(file.parent, nameMatchingApkFile)
newMappingFile.delete() //clean-up if exists already
file.renameTo(newMappingFile)
}
}
}
}
Note, that variant.getBuildType().isMinifyEnabled() is not used since we are using DexGuard.
The code above makes mapping file's name match apk's file name.
Just in case, if you need to change apk name - following could be used:
android {
defaultConfig {
//resulting apk will looks like: "archive base name" + -<flavour>-<buildType>.apk
archivesBaseName = "$applicationId-$versionName"
}
}
Many thanx to Sergii Pechenizkyi who helped me to found this good solution.
To implement copying of proguard mapping files for each flavor we can create "root" task copyProguardMappingTask
and number of dynamic tasks for each flavor
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
}
}
}
afterwards we should run this task after assembling our project. I use jenkins and my tasks option looks like
gradle clean assembleProjectName copyProguardMapping
It works like a charm.
All these answers used copy to rename the file. I didn't want to move the file however, I just wanted to change it's name, keeping in mind the build type and flavor.
I based myself on the code from the other posters here and changed it up a bit. Since Minify can be false, while still using proguard, I just check if the file is present.
Following code accomplishes just that.
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)
}
}
}
}
NOTE
You could probably use this code to move the file as well.
the .renameTo() method expects a full path, If you change the path, I would suppose you effectively move the File to another place.
Simpler solution.
applicationVariants.all { variant ->
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
copy {
from variant.mappingFile
into "${rootDir}/proguardTools"
rename { String fileName ->
"mapping-${variant.name}.txt"
}
}
}
}
}