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

后端 未结 12 1644
灰色年华
灰色年华 2020-11-30 08:48

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

相关标签:
12条回答
  • 2020-11-30 09:23

    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:

    1. The module name is hardcoded ("app"), which is not ideal since in a lot of cases (including mine) that will not be true. It is better to dynamically detect the module name.
    2. The mapping file also only conforms to the Windows file system by having backward escaped slashes ("\"). If you are on a *NIX system like Linux or Mac, you need to replace those with forward non escaped slashes ("/")
    3. Changed a bit the renaming of the .apk file to include the project name and added a date/time stamp at the end.

    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 "";
        }
    }
    
    0 讨论(0)
  • 2020-11-30 09:25

    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")
                }
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-11-30 09:27

    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"
        }
    }
    
    
    0 讨论(0)
  • 2020-11-30 09:30

    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.

    0 讨论(0)
  • 2020-11-30 09:30

    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.

    0 讨论(0)
  • 2020-11-30 09:34

    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"
                        }
                    }
                }
            }
        }
    
    0 讨论(0)
提交回复
热议问题