rcperso
rcperso

Reputation: 500

Gradle copy and rename in loop

I'm working with Android Studio 3.

For each flavor, I want to copy mapping.txt and rename it.

My Gradle task :

task deployApks(type: Copy) {
        android.applicationVariants.all { variant ->
            if (variant.buildType.name == 'release') {
            variant.outputs.all {
                  def flavor = variant.productFlavors.name.get(0)

                  def dirApk = System.getProperty("user.dir") + '/app/build/' + flavor + '/release/'
                  def dirMapping = System.getProperty("user.dir") + '/app/build/outputs/mapping/' + flavor + '/release/'

                  //copy apk and mapping.txt
                  from dirApk, dirMapping
                  include '*-release.apk', 'mapping.txt'
                  into dirDeploy

                  //rename mapping.txt
                  from dirDeploy
                  include 'mapping.txt'
                  into dirDeploy
                  rename 'mapping.txt', 'mapping-' + flavor + '.txt'
                  println("Rename mapping.txt tomapping-" + flavor + ".txt")
             }
        }
    }
}

What I want in deploy directory :

What I get :

Is gradle copy asynchronous.?

It looks like if renaming is done after all copies.

Upvotes: 1

Views: 3121

Answers (2)

equiman
equiman

Reputation: 8132

I think the key is variant.assemble.doLast. I'm making first all apk files and when finish run doLast task copying and renaming mapping.txt files.

Gradle 4 (compatible)

// Map for the version code that gives each ABI a value.
ext.abiCodes = ['armeabi':3, 'armeabi-v7a':4, 'arm64-v8a':5, 'mips':6, 'x86':7, 'x86_64':8].withDefault {0}

import com.android.build.OutputFile
android.applicationVariants.all { variant ->
    def customName = ""
    if (project.hasProperty('projectName')) {
        customName = projectName
    } else {
        customName = project.name
    }

    def flavorName = variant.productFlavors[0].name
    def buildType = variant.variantData.variantConfiguration.buildType.name
    def abiVersionCode = ""
    def abiName = ""
    def fileName = ""
    def mappingDir = "${rootDir}/build/outputs/mapping/${flavorName}/${buildType}"


    variant.outputs.all { output ->
        abiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
        if (abiVersionCode != null) {
            output.versionCodeOverride = abiVersionCode * 1000 + variant.versionCode
        }
        abiName = output.getFilter(OutputFile.ABI)
        if (abiName == null) {
            abiName = "universal"
            output.versionCodeOverride = 1 * 1000 + variant.versionCode
        }

        fileName = customName + "_" + variant.versionName + "-" + flavorName + "-" + abiName + "-" + buildType + "-" + output.versionCode
        outputFileName = new File("${fileName}.apk")
    }


    variant.assemble.doLast {
        variant.outputs.all { output ->
            if (buildType == "release") {
                def mappingFile = "${mappingDir}/mapping.txt"
                def newMappingName = "${fileName}-mapping.txt"

                delete "${output.outputFile.parent}/${newMappingName}"
                copy {
                    from "${mappingFile}"
                    into "${rootDir}"
                    rename { String mappingName ->
                        "${output.outputFile.parent}/${newMappingName}"
                    }
                }
            }

            delete "${output.outputFile.parent}/output.json"
        }
    }
}

Upvotes: 0

Opal
Opal

Reputation: 84756

You may not know but gradle build consists of 3 phases:

  • initialisation
  • configuration
  • execution

Task (including Copy you used) actions (a task is a collection of actions run in order) are configured in the second phase. Eve if you put loop in task's body the last iteration will win. The easiest way is to change your task to the following (copying manually):

task deployApks {
  doLast {
    android.applicationVariants.all { variant ->
      if (variant.buildType.name == 'release') {
      variant.outputs.all {
        def flavor = variant.productFlavors.name.get(0)

        def dirApk = System.getProperty("user.dir") + '/app/build/' + flavor + '/release/'
        def dirMapping = System.getProperty("user.dir") + '/app/build/outputs/mapping/' + flavor + '/release/'

        //copy apk and mapping.txt
        copy {
          from dirApk, dirMapping
          include '*-release.apk', 'mapping.txt'
          into dirDeploy
          rename 'mapping.txt', 'mapping-' + flavor + '.txt'
        }
       }
      }
    }
  }
}

If that solves the problem - (you don't need to task caching) you can work with. Otherwise you need to configure Copy task appropriately or even write a custom task.

Upvotes: 2

Related Questions