How to Change the Proguard Mapping File Name in Gradle for Android Project

How to change the proguard mapping file name in gradle for Android project

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"
}
}

Append version number into proguard mapping folder

Following¹ will rename mapping.txt to mapping-release-1.0.1.txt in the same folder.

In the module build.gradle file:

android {
// lots of gradle code

// The following portion renames the mapping.txt file.
applicationVariants.all { variant ->
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {
variant.mappingFile.renameTo(file(
"${variant.mappingFile.parent}/mapping-${variant.name}-${variant.versionName}.txt"))
}
}
}
}

You may also use variant.versionCode or other options in the file name.

Hope this helps.

Difficulties setting up Gradle to send ProGuard mapping files to Firebase

gradle.properties is owned and managed completely by you. You have to create it if it doesn't already exist. This means you should probably read the Gradle documentation on it to best understand how it provides properties to your builds, and which location is best for your properties.

You are not even obliged to use gradle.properties. You can also specify all the properties for the Crash Reporting plugin via the command line.

When you specify a path for the service account file, you should specify the full, unambiguous path to the file. In your example, it looks like you're assuming that it will look under the app directory in your project. If you want to do that, you still have to give the full path to the file.

Where does Android Studio save the ProGuard mapping file?

It should be located at build/outputs/proguard/release/mapping.txt in your application module's directory.

In the latest version of ProGuard and Android Studio, the file is located at build/outputs/mapping/release/mapping.txt.

How to get ProGuard mapping file of previous release build

The mapping file is overwritten after every build so you probably lost it for good.

The best approach I can think of would be versioning your code with some VCS (Git, for example) and moving the mapping file to a location that is not being gitignored.

To move the generated proguard mapping file to a different path check this answer. You can even rename it if you like.

How to use gradle and proguard printmapping to create out.map file with version code

So, this is how it done

first define a function to get the version name

def getVersionName() {
File stringsXmlFile = new File("src\\main\\res\\values\\strings.xml")
String contents = stringsXmlFile.getText()
String version = contents.find("<string name=\"version\">[^<]*</string>");
version = version.replace("<string name=\"version\">", "").replace("string>", "")
version = version.replace("<", "")
version = version.substring(0, version.length() - 1)

return version
}

second, define after task function

gradle.taskGraph.afterTask { Task task, TaskState state ->
if (task.name.equals("assembleRelease")) {

File proguard = new File("build\\outputs\\apk\\out.map")
proguard.renameTo("build\\outputs\\apk\\out-" + getVersionName() + ".map")

}
}

that's it.

Gradle, task to copy mapping file

This is the snippet I use. It does depend on having a productFlavor defined but that is only to help name the file and allow the same snippet to be reused in multiple projects without modification but that dependency could be refactored out if you wanted a different filename format.

As it stands, the apk and the mapping file (if required) will be copied to the defined basePath in the format:

FilePath\appname\appname buildtype versionname (versioncode)

e.g
A:\Common\Apk\MyAppName\MyAppName release 1.0 (1).apk
and
A:\Common\Apk\MyAppName\MyAppName release 1.0 (1).mapping

Amend as you see fit.

android {

productFlavors {
MyAppName {
}

}

//region [ Copy APK and Proguard mapping file to archive location ]

def basePath = "A:\\Common\\Apk\\"

applicationVariants.all { variant ->
variant.outputs.each { output ->

// Ensure the output folder exists
def outputPathName = basePath + variant.productFlavors[0].name
def outputFolder = new File(outputPathName)
if (!outputFolder.exists()) {
outputFolder.mkdirs()
}

// set the base filename
def newName = variant.productFlavors[0].name + " " + variant.buildType.name + " " + defaultConfig.versionName + " (" + defaultConfig.versionCode + ")"

// The location that the mapping file will be copied to
def mappingPath = outputPathName + "\\" + newName + ".mapping"

// delete any existing mapping file
if (file(mappingPath).exists()) {
delete mappingPath
}

// Copy the mapping file if Proguard is turned on for this build
if (variant.getBuildType().isMinifyEnabled()) {
variant.assemble.doLast {

copy {
from variant.mappingFile
into output.outputFile.parent
rename { String fileName ->
newName + ".mapping"
}
}
}
}

// Set the filename and path that the apk will be created at
if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {

def path = outputPathName + "\\" + newName + ".apk"
if (file(path).exists()) {
delete path
}
output.outputFile = new File(path)

}
}

}

//endregion

}



Related Topics



Leave a reply



Submit