Arthur Dent
Arthur Dent

Reputation: 1258

How to get current buildType in Android Gradle configuration

I want to dynamically add a dependency in an Android Gradle project based on the current buildType. I know I can specify the buildType in the dependency:

compile project(path: ':lib1', configuration: 'debug')

But how can I use the current buildType to specify which variant of the library I want to import, so that a debug or release build automatically imports the debug or release variant of the library? What I want is something like this (where currentBuildType is a variable containing the name of the currently used buildType):

compile project(path: ':lib1', configuration: currentBuildType)

The library project I want to import has set publishNonDefault true, so all buildTypes are published.

Upvotes: 38

Views: 49271

Answers (8)

Shooky
Shooky

Reputation: 1299

You can use

if (gradle.startParameter.taskNames.contains("assembleExample")) {
    // do stuff
}

That variable will be set before the buildConfig block is evaluated

Upvotes: 25

rpattabi
rpattabi

Reputation: 10207

Based on Shooky's answer and JLund's comment, this is what works for me. I have this code in my app build.gradle towards the end:

ext.getCurrentBuildType = {
    def isDebug = gradle.startParameter.taskRequests.any {
                            it.args.any { it.endsWith("Debug") } }
    return isDebug ? "Debug" : "Release"
}

Just call it afterEvaluate. Example:

afterEvaluate {
    tasks.getByName("externalNativeBuild${ext.getCurrentBuildType()}")
         .dependsOn myOtherTask
}

Apparently, gradle.startParameter has plenty of info about current run. Take a look at the doc.

Upvotes: 2

X Fa
X Fa

Reputation: 1

Running Gradle task 'assembleRelease'...

Upvotes: -4

Braian Coronel
Braian Coronel

Reputation: 22905

The idea of executing a certain code based on the environment should be through dependency injection.


Take into account to use the following declaration only for exceptional configurations because in general it should not happen that in the code there are conditionals that make references to the environments.

build.gradle

android {

    def TRUE = "true"
    def FALSE = "false"
    def IS_DEV = "IS_DEV"
    def IS_RELEASE = "IS_RELEASE"

    defaultConfig {
        //...
        buildConfigField BOOLEAN, IS_DEV, FALSE
        buildConfigField BOOLEAN, IS_RELEASE, FALSE
    }

    buildTypes {
        debug {
            buildConfigField BOOLEAN, IS_DEV, TRUE
        }
        release {
            buildConfigField BOOLEAN, IS_RELEASE, TRUE
        }
    }

}

GL

Upvotes: -3

Reinherd
Reinherd

Reputation: 5504

This one is quite simple:

android {
    applicationVariants.all { variant ->
        variant.buildType.name // this is the value!
    }
}

Edit: Apparently at some point with gradle update, this is not working as I mentioned in a comment below. So I'd recommend checking other options.

Upvotes: 6

what
what

Reputation: 11

// declare a custom task class so you can reuse it for the different
// variants
class MyTask extends DefaultTask {
     String mVariantName;
     public void setVariantName(String variant) {mVariantName = variant;}
     public String getVariantName() { return mVariantName; }
     @TaskAction
     void action(){
        // do stuff
     }
}

// put this after your `android{}` block.
android.applicationVariants.all { variant ->
    def taskName = "myTask_$variant.name"
    task "$taskName"(type: MyTask) << {
        // you can setup this task to various info regarding
        // variant
        variantName = variant.name
    }
    variant.assemble.dependsOn (taskName)
}

See Advance customization for more details of what you can extract from the variant variable.

now you it will properly hookup your MyTask into to the chain. Doing it this way should also cleanly handle building multiple flavors all at once as it creates a new instance of MyTask for each variant.

Upvotes: 1

Alexander Blinov
Alexander Blinov

Reputation: 393

Add a task which depends on each assembleXxx task and property setting up after it invoked

ext {
    currentConfig = ""
}
task generateConfigProperty(dependsOn: 'installDebug') {

    android.applicationVariants.all { variant ->
        variant.outputs.each { output ->

            def taskName = "taskindicate$output.name"
            task "$taskName"() << {
                project.ext.set("currentConfig", "$output.name")
            }
            output.assemble.dependsOn "taskindicate$output.name"
        }
    }

}

task getConfig(dependsOn: ['installDebug', 'generateConfigProperty']) << {
    println("My config is $currentConfig")
}

took idea from the answer

Upvotes: 12

Arthur Dent
Arthur Dent

Reputation: 1258

I could not find a clean way to get the current build type during the configuration phase of Gradle. Instead I define the dependency for each build type separately like that:

debugCompile project(path: ':lib1', configuration: 'debug')
releaseCompile project(path: ':lib1', configuration: 'release')

If you have many build types and many project dependencies this can get very verbose, but it is possible to add a function to make the dependency a one-liner. You need to add this to your main Gradle build file:

subprojects {
    android {
        dependencies.metaClass.allCompile { dependency ->
            buildTypes.each { buildType ->
                "${buildType.name}Compile" project(path: ":${dependency.name}", configuration: buildType.name)
            }
        }
    }
}

Then you can add project dependencies in your Gradle modules like this:

allCompile project(':lib1')

If you also use build flavors you would have to adapt the solution. See this link for a documentation of the feature: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-Publication

Please note that the Android team is working on an improvement for this behaviour: https://code.google.com/p/android/issues/detail?id=52962

Upvotes: 14

Related Questions