Giulio Bider
Giulio Bider

Reputation: 1406

How to get current flavor in gradle

I have two product flavors for my app:

productFlavors {
    europe {
        buildConfigField("Boolean", "BEACON_ENABLED", "false")
    }

    usa {
        buildConfigField("Boolean", "BEACON_ENABLED", "true")
    }
}

Now I want to get the current flavor name (which one I selected in Android Studio) inside a task to change the path:

task copyJar(type: Copy) {
    from('build/intermediates/bundles/' + FLAVOR_NAME + '/release/')
}

How can I obtain FLAVOR_NAME in Gradle?

Thanks

Upvotes: 86

Views: 89704

Answers (13)

Ross
Ross

Reputation: 1659

Here is the "official" getFlavour() function you may find in react-native-config package. Probably it's most accurate.

def getCurrentFlavor() {
    Gradle gradle = getGradle()

    // match optional modules followed by the task
    // (?:.*:)* is a non-capturing group to skip any :foo:bar: if they exist
    // *[a-z]+([A-Za-z]+) will capture the flavor part of the task name onward (e.g., assembleRelease --> Release)
    def pattern = Pattern.compile("(?:.*:)*[a-z]+([A-Z][A-Za-z0-9]+)")
    def flavor = ""

    gradle.getStartParameter().getTaskNames().any { name ->
        Matcher matcher = pattern.matcher(name)
        if (matcher.find()) {
            flavor = matcher.group(1).toLowerCase()
            return true
        }
    }

    return flavor
}

Upvotes: 0

Poiana Apuana
Poiana Apuana

Reputation: 1446

How to get current flavor name

I have developed the following function, returning exactly the current flavor name:

def getCurrentFlavor() {
    Gradle gradle = getGradle()
    String  tskReqStr = gradle.getStartParameter().getTaskRequests().toString()

    Pattern pattern

    if( tskReqStr.contains( "assemble" ) ) // to run ./gradlew assembleRelease to build APK
        pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
    else if( tskReqStr.contains( "bundle" ) ) // to run ./gradlew bundleRelease to build .aab
        pattern = Pattern.compile("bundle(\\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 ""
    }
}

You need also

import java.util.regex.Matcher
import java.util.regex.Pattern

at the beginning or your script. In Android Studio this works by compiling with "Make Project" or "Debug App" button.

How to get current build variant

def getCurrentVariant() {
    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(2).toLowerCase()
    }else{
        println "NO MATCH FOUND"
        return ""
    }
}

How to get current flavor applicationId

A similar question could be: how to get the applicationId? Also in this case, there is no direct way to get the current flavor applicationId. Then I have developed a gradle function using the above defined getCurrentFlavor function as follows:

def getCurrentApplicationId() {
    def currFlavor = getCurrentFlavor()

    def outStr = ''
    android.productFlavors.all{ flavor ->

        if( flavor.name==currFlavor )
            outStr=flavor.applicationId
    }

    return outStr
}

Voilà.

Upvotes: 109

Nanda Gopal
Nanda Gopal

Reputation: 2699

Just add the following in your build.gradle (app level)

def getCurrentFlavour() {
  Gradle gradle = getGradle()
  String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
  print(tskReqStr.toString())

  Pattern pattern;
  if( tskReqStr.contains( "assemble" ))
    pattern = Pattern.compile("assemble(\\w+)(Release|Staging|Debug)")
  else
    pattern = Pattern.compile("generate(\\w+)(Release|Staging|Debug)")
  Matcher matcher = pattern.matcher( tskReqStr )
  if( matcher.find() ) {
    def value = matcher.group(1).toLowerCase()
    return value
  } else {
    return "";
  }
}

Now Inside android tag,

android {  
// android tag starts
 defaultConfig {
  - - - - - - - - 
  - - - - - - - - 
 }
 - - - - - - - - 
 - - - - - - - - 
 
 def flavourName = getCurrentFlavour()
  if (flavourName == "Dev") {
    println("This is Dev")
   } else if (flavourName == "Staging") {
    println("This is Staging")
   } else if (flavourName == "Production") {
    println("This is Production")
   } else {
    println("NA")
   }
// android tag ends
}

Now Sync & Build your project.

Upvotes: 2

wamfous
wamfous

Reputation: 2309

A combination of aforementioned snippets was needed for me to get this to work.

My full answer to the original question would look like this:

android {
    ...
    applicationVariants.all { variant ->
        task "${variant.getName()}CopyJar"(type: Copy) {
            from("build/intermediates/bundles/${variant.getFlavorName()}/release/")
        }
    }
}

This creates a <variant>CopyJar task for each variant, which you can then run manually.

Upvotes: 1

user1506104
user1506104

Reputation: 7076

How to get the flavor name or build variant from a prebuild task? This is what solved my issue. I added getCurrentFlavor() or getCurrentVariant() (from @Poiana Apuana answer) into my task's dependOn like so:

task getCurrentFlavor() {
    // paste Poiana Apuana's answer
}

// OR
//task getCurrentVariant() {
//  // paste Poiana Apuana's answer
//}

task myTask(type: Copy) {
    dependsOn getCurrentFlavor
    // or dependsOn getCurrentVariant
    println "flavor name is $projectName"
    ...
}
preBuild.dependsOn myTask

Check original problem here.

Upvotes: 0

Ali Asadi
Ali Asadi

Reputation: 987

Use:

${variant.baseName}.apk"

This return current flavor name

Full Answer

android.applicationVariants.all { variant ->
    variant.outputs.all {
        outputFileName = "${variant.baseName}.apk"
    }
}

Upvotes: 4

Timtcng.sen
Timtcng.sen

Reputation: 383

I use this

${variant.getFlavorName()}.apk

to format file name output

Upvotes: 29

wonsuc
wonsuc

Reputation: 3625

I slightly changed Poiana Apuana's answer since my flavor has some capital character.

REASON
gradle.getStartParameter().getTaskRequests().toString() contains your current flavor name but the first character is capital.
However, usually flavor name starts with lowercase. So I forced to change first character to lowercase.

def getCurrentFlavor() {
    Gradle gradle = getGradle()
    String taskReqStr = gradle.getStartParameter().getTaskRequests().toString()
    Pattern pattern
    if (taskReqStr.contains("assemble")) {
        pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
    } else {
        pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
    }
    Matcher matcher = pattern.matcher(taskReqStr)
    if (matcher.find()) {
        String flavor = matcher.group(1)
        // This makes first character to lowercase.
        char[] c = flavor.toCharArray()
        c[0] = Character.toLowerCase(c[0])
        flavor = new String(c)
        println "getCurrentFlavor:" + flavor
        return flavor
    } else {
        println "getCurrentFlavor:cannot_find_current_flavor"
        return ""
    }
}

Upvotes: 6

B3n
B3n

Reputation: 583

You can use gradle.startParameter.taskNames[0]

Upvotes: 2

Nick
Nick

Reputation: 2903

get SELECTED_BUILD_VARIANT from the .iml file after gradle sync completes You can either load it using an xml parser, or less desireable, but probably faster to implement would be to use a regex to find it.

<facet type="android" name="Android">
  <configuration>
    <option name="SELECTED_BUILD_VARIANT" value="your_build_flavorDebug" />
        ...

(not tested, something like this:)

/(?=<name="SELECTED_BUILD_VARIANT".*value=")[^"]?/

Upvotes: 4

Dartan Li
Dartan Li

Reputation: 227

you should use this,${variant.productFlavors[0].name},it will get productFlavors both IDE and command line.

Upvotes: 14

Nazar Ivanchuk
Nazar Ivanchuk

Reputation: 127

my solution was in that to parse gradle input parameters.

Gradle gradle = getGradle()

Pattern pattern = Pattern.compile(":assemble(.*?)(Release|Debug)");
Matcher matcher = pattern.matcher(gradle.getStartParameter().getTaskRequests().toString());
println(matcher.group(1))

Upvotes: 6

azertiti
azertiti

Reputation: 3150

This is what I used some time ago. I hope it's still working with the latest Gradle plugin. I was basically iterating through all flavours and setting a new output file which looks similar to what you are trying to achieve.

applicationVariants.all { com.android.build.gradle.api.ApplicationVariant variant ->
    for (flavor in variant.productFlavors) {
        variant.outputs[0].outputFile = file("$project.buildDir/${YourNewPath}/${YourNewApkName}.apk")
    }
}

Upvotes: 7

Related Questions