Как изменить имя файла сопоставления proguard в проекте gradle для Android

У меня есть проект android на основе gradle, и я хочу изменить отображение.имя файла txt после его создания для моей сборки. Как это можно сделать?

upd

Как это можно сделать в build.Gradle в? Поскольку у меня есть доступ к моим вкусам и другим жестким, я хотел бы создать имя файла сопоставления на основе версии варианта flavor/build.

9 ответов


простое решение.

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.pro файл:

-printmapping path/to/your/file/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.

но я думаю, что существует лучшее решение.


С момента последнего варианта обновления.mappingFile больше не доступен. (Я использую ProGuard версии 4.7, AndroidStudio 2.0)

Это (часть) моей сборки.файл 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")
            }
        }
    }

}

многие thanx к Сергей Pechenizkyi кто помог мне найти это хорошее решение.

чтобы реализовать копирование файлов отображения proguard для каждого вкуса, мы можем создать "корневую" задачу copyProguardMappingTask и количество динамических задач для каждого вкуса

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

это работает как шарм.


Это вариант igorpst это но сопоставление переименовывает.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")
            }
        }
    }
}

все эти ответы использовали copy для переименования файла. Я не хотел перемещать файл, однако, я просто хотел изменить его имя, имея в виду тип сборки и вкус.

я основывался на коде из других плакатов здесь и немного изменил его. Поскольку Minify может быть false, все еще используя 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)
            }
        }
    }
}

Примечание

вы могли вероятно, используйте этот код для перемещения файла.

the .метод renameTo () ожидает полный путь, Если вы измените путь, я бы предположил, что вы эффективно переместите файл в другое место.


ранее ответа отлично работал для меня, пока Android 3.0/Android Gradle Plugin 3.0 не устарел BuildType.isMinifyEnabled().

я разработала следующее решение, которое не использует устаревший метод:

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

решение Pinhassi выше отлично работает, и оно соответствует последним изменениям Gradle. Есть несколько вещей, хотя, что я должен был изменить:

  1. имя модуля жестко закодировано ("приложение"), что не идеально, так как во многих случаях (включая мой) это не будет правдой. Лучше динамически определять имя модуля.
  2. файл сопоставления также соответствует только файловой системе Windows, имея обратные экранированные косые черты ("\"). Если вы находитесь на * NIX система, такая как Linux или Mac, вам нужно заменить их прямыми не экранированными косыми чертами ("/")
  3. изменилось переименованием .apk файл, чтобы включить имя проекта и добавлен штамп даты/времени в конце.

вот готовый код:

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