web-dev-qa-db-ja.com

AndroidプロジェクトのGradleでProguardマッピングファイル名を変更する方法

Androidプロジェクトがgradleに基づいており、ビルド用に生成された後にmapping.txtファイル名を変更したいのですが、どうすればよいですか?

upd

どのようにbuild.gradleで実行できますか?フレーバーやその他の硬いものにアクセスできるので、フレーバー/ビルドバリアントバージョンに基づいてマッピングファイル名を作成したいと思います。

23
olegflo

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

その後、プロジェクトをアセンブルした後でこのタスクを実行する必要があります。私はジェンキンスを使用しており、私のタスクオプションは次のようになります

gradle clean assembleProjectName copyProguardMapping

それは魅力のように働きます。

3
olegflo

よりシンプルなソリューション。

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

このコマンドをproguard-rules.proファイルで使用します。

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

ファイルは_{root}/path/to/your/file_という名前で_file_name.txt_の部分に書き込まれます。

フレーバーごとに異なる設定が必要な場合は、フレーバーに対して多くのプロガードルールを定義できます

もう1つアイデアが見つかりましたが、それが正しい方法かどうかはわかりません。

パスをフレーバーで定義できます。

_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_を変更できます。

しかし、私はそれがより良い解決策があると思います。

7

これは igorpst's answer のバリエーションですが、アプリのバージョン名を正確に含むapkの名前と一致するようにmapping.txtの名前を変更します。 this answer で説明されているように、これをコードと組み合わせてAPKにバージョン番号を付けました。 $variant.baseNameを見つけるために、gradleのソースコードを調べなければなりませんでした

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")
            }
        }
    }
}
4
Jon

最後の更新以降、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")
            }
        }
    }

}
4
Asaf Pinhassi

variant.assembleは廃止され、以前の変更を組み込んだ推奨ソリューションです。

archivesBaseName = "MyCompany-MyAppName-$versionName"
...
applicationVariants.all { variant ->
    variant.assembleProvider.get().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)
        }
    }
}

APKの代わりにApp Bundle(aab)を使用している場合は、これをafter the Android =セクション:

afterEvaluate {
    bundleRelease.doLast {
        Android.applicationVariants.all { variant ->
            if (variant.buildType.name == 'release') {
                tasks.create(name: "renameMappingFile") {
                    if (variant.mappingFile != null && variant.mappingFile.exists()) {
                        variant.mappingFile.renameTo(variant.mappingFile.parent + "/$variant.baseName-$versionName-${new Date().format('yyyy-MM-dd_HHmm')}-mapping.txt")
                    }
                }
            }
        }
    }
}

最後の例でもapkのbundleReleaseassembleReleaseにスワップします。

更新:ただし、通常のデバッグを携帯電話に直接ビルドしようとすると、最後は機能しません。エラー:

タイプorg.gradle.api.Projectのプロジェクト ':app'の不明なプロパティ 'bundleRelease'を取得できませんでした。

これらすべての回答では、copyを使用してファイルの名前を変更しました。ファイルを移動したくはありませんでしたが、ビルドタイプとフレーバーを考慮して、ファイル名を変更したいと思いました。

ここにある他のポスターのコードに基づいて、少し変更しました。 Minifyはfalseである可能性があるため、まだプロガードを使用しているので、ファイルが存在するかどうかを確認するだけです。

次のコードはそれを実現します。

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()メソッドは絶対パスを想定しています。パスを変更した場合、ファイルを別の場所に効果的に移動すると思います。

2
SnyersK

Android Studio Gradle Plugin Version 3.3.0(January 2019))の新機能これにより、Android 3.0/Android Gradle Pluginの以前の問題が解消されます。 3.0は非推奨BuildType.isMinifyEnabled()で、gradleプラグインは非推奨variant.getAssemble()です。

applicationVariants.all { variant ->
    variant.assembleProvider.get().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)
        }
    }
}
1
Jon

上記のPinhassiのソリューションは優れており、最新のGradleの変更に準拠しています。変更しなければならないことがいくつかあります。

  1. モジュール名はハードコーディング(「アプリ」)されていますが、多くの場合(私のものを含む)は当てはまらないため、これは理想的ではありません。モジュール名を動的に検出することをお勧めします。
  2. マッピングファイルは、バックスラッシュスラッシュ( "\")を使用することにより、Windowsファイルシステムにのみ準拠します。 LinuxやMacなどの* NIXシステムを使用している場合は、エスケープしないスラッシュ( "/")をスラッシュに置き換える必要があります。
  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 "";
    }
}
0
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"
                    }
                }
            }
        }
    }
}
0
jp1017