How to loop all source-sets in the kotlin DSL? The below groovy code loops all sourceSets including 'multiplicative' like androidTestFoobarProdDebug
flavorDimensions("brand", "releaseType")
productFlavors {
create("prod") {
dimension = "releaseType"
}
create("foobar") {
dimension = "brand"
}
}
sourceSets.all { com.android.build.api.dsl.AndroidSourceSet sourceSet ->
// Also prints foorbarProd
println("0 "+sourceSet.name)
}
sourceSets.all {
println("1 "+it.name)
}
but this kotlin-code does not loop the multiplicative concatenated flavor-dimensions like foobarProdDebug
sourceSets.all { sourceSet ->
println(sourceSet.name) // does not print foobarProd
true // seems its a predicate in kotlin
}
People at Google were so kind to help me out here:
Sadly this seems like the mixing of kotlin's all extension method on collection (which is not lazy) and gradle's DomainObjectContainer.all (which is lazy).
If you change
sourceSets.all { sourceSet -> //: com.android.build.api.dsl.AndroidSourceSet ->
println("sourceSet.name = \"src/${name}/svg\"")
true // seems its a predicate in kotlin
}
to
sourceSets.all {// this: com.android.build.api.dsl.AndroidSourceSet ->
println("sourceSet.name = \"src/${name}/svg\"")
// Not a kotlin.sequences.all call anymore so nothing to return
}
it works.
Here's the full kotlin solution:
flavorDimensions("brand", "releaseType")
productFlavors {
create("prod") {
dimension = "releaseType"
}
create("foobar") {
dimension = "brand"
}
}
sourceSets.all {
println(name)
}
During migration build script from groovy to kotlin I met problem with excluding build variants.
In groovy it's pretty easy:
android {
variantFilter { variant ->
if (variant.name == "lorempisum") {
setIgnore(true)
}
}
}
but in kotlin similar thing does not work. It seems to be ok in android studio, but during compilation it throws Unresolved reference: isIgnore
android {
variantFilter {
if (buildType.name == "lorempisum") {
isIgnore = true
}
}
}
from the other side this reports Unresolved reference: setIgnore, but works during compilation
android {
variantFilter {
if (buildType.name == "lorempisum") {
this.setIgnore(true)
}
}
}
Anybody has idea how do it in right way?
I'm using kotlin 1.3.72, android studio 4.0.1 and gradle 6.5.1
---- EDIT ----
I fix example ignore -> isIgnore in second block, it also not works
Soultion is ignore = true with a little deatil.
This works if you keep in top-level build.gradle.kts this line:
classpath("com.android.tools.build:gradle:4.0.1")
and not really only on buildSrc on this:
implementation("com.android.tools.build:gradle:4.0.1")
Use the beforeVariants block:
androidComponents {
beforeVariants { variantBuilder ->
// To check for a certain build type, use variantBuilder.buildType == "<buildType>"
if (variantBuilder.productFlavors.containsAll(listOf("api" to "minApi21", "mode" to "demo"))) {
// Gradle ignores any variants that satisfy the conditions above.
variantBuilder.enabled = false
}
}
}
You should first update to the last version of android studio and the plugins.
And try this
variantFilter {
this.ignore = name == "lorempisum"
}
I define a variable in order to add different plugins to project, but it seems not working at all.
variantFilter { variant ->
def names = variant.flavors*.name
println names
if (names.contains("someFlavor")) {
google_service = false
}else{
google_service = true
}
}
My Question is very direct and easy to understand.
Question
In Gradle, is there any way I can get the current build type at runtime. For example, when running an assembleDebug task, can tasks within the build.gradle file make decisions based on the fact that this task is related to the debug build variant?
Sample Code
apply plugin: 'com.android.library'
ext.buildInProgress = ""
buildscript {
repositories {
maven {
url = url_here
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
configurations {
//get current build in progress here e.g buildInProgress = this.getBuildType()
}
android {
//Android build settings here
}
buildTypes {
release {
//release type details here
}
debug {
//debug type details here
}
anotherBuildType{
//another build type details here
}
}
}
dependencies {
//dependency list here
}
repositories{
maven(url=url2_here)
}
task myTask{
if(buildInProgress=='release'){
//do something this way
}
else if(buildInProgress=='debug'){
//do something this way
}
else if(buildInProgress=='anotherBuildType'){
//do it another way
}
}
In Summary
Is there a way for me to get exactly the build type in progress within myTask{}?
You can get the exact build type by parsing your applicationVariants:
applicationVariants.all { variant ->
buildType = variant.buildType.name // sets the current build type
}
A implementation could look like the following:
def buildType // Your variable
android {
applicationVariants.all { variant ->
buildType = variant.buildType.name // Sets the current build type
}
}
task myTask{
// Compare buildType here
}
Also you can check this and this similar answers.
Update
This answer by this question helped the questioner to settle the problem.
This worked for me
applicationVariants.all { variant ->
def variantType = variant.buildType.name
println "Variant type: $variantType"
if (variantType == "debug") {
// do stuff
}
}
You should getBuildConfigFields().get("MY_BUILD_TYPE").getValue())
https://stackoverflow.com/a/59994937/5279996
GL
If you want to suffix the buildtype name to the versionname (like me) just add this line to the version name:
debug {
versionNameSuffix "-debug"
}
This way you can identify the build type in the build name. And it works without declaring anything else.
Correct way for getting the current buildType being used during build in Kotlin programming language for android platform (logic is the same for Java)
project.afterEvaluate {
this.android().variants().all {
this.assembleProvider.configure {
this.doLast{
val variant = this#all
variant.outputs
.map
.forEach{
//do something with current buildType, or build flavor or whatever
println(variant.flavorName)
println(variant.buildType)
}
}
}
}
}
I'm getting build type in this way:
BuildConfig.BUILD_TYPE
If you need to check what is the current build type, create an enum class in your utils package and use it in your if statement:
enum class Environment(val value: String) {
RELEASE("release"),
LOCAL("local"),
STAGING("staging"),
DEBUG("debug")
}
Your if/when statement:
if (BuildConfig.BUILD_TYPE == Environment.RELEASE.value) {
//TODO
} else if(...)
or through when:
when(BuildConfig.BUILD_TYPE) {
Environment.RELEASE.value -> { //TODO }
Environment.LOCAL.value -> { // TODO }
// etc.
}
I checked other answers, nothing works.
What's below will help.
In your build.gradle (:app):
tasks.all { Task task ->
if (task.name == "preDebugBuild") {
doFirst {
//for debug build
}
} else if (task.name == "preReleaseBuild") {
doFirst {
//for release build
}
}
}
dependencies {
...
}
Be aware, the code that you put inside will not be executed when you change the build variant, but when you build app.
Try like this in your gradle : It works fine for me
//get current build all params as string
def buildParams = getGradle().getStartParameter().toString().toLowerCase();
applicationVariants.all { variant ->
variant.outputs.all {
def typename = variant.buildType.name.toLowerCase();
//and check build state in all variants
if(buildParams.contains(typename)) {
// finally, you get what you want.
}
}
}
You can get the exact build type by parsing your applicationVariants:
applicationVariants.all { variant ->
buildType = variant.buildType.name // sets the current build type
}
Here's the approach I used to detect the runtime build type without declaring any variables at build time.
def isCurrentBuildType(buildType) {
return gradle.getStartParameter().taskNames.find({ it.endsWith(buildType) }) != null
}
print(isCurrentBuildType("Release")) //prints true if the current build type is release.
Note that the first letter should be capital (e.g. assembleRelease, bundleRelease)
I've been looking for a few minutes over the internet on how to create functions and call them inside build.gradle without success. Since I found nothing I'm not sure if I'm searching for the right concept-keywords or if that's even possible.
I have two buildTypes:
release {
}
debug {
}
And I woud like to call this snippet() below inside both of them without duplicating it, or in other words, to create a function:
def propsFile = rootProject.file('properties')
def M_PROP = "mProp"
if (propsFile.exists()) {
//Math
}
Generating something like:
buildTypes {
release {
snippet()
}
}
debug {
snippet()
}
}
is that possible and how am I able to do this?
Perhaps you want
buildTypes {
[release, debug].each { buildType ->
if (foo) {
buildType.doStuff()
}
}
}
Or maybe
ext.snippet = { buildType ->
if (foo) {
buildType.doStuff()
}
}
buildTypes {
snippet(release)
snippet(debug)
}
Note: There's also the with { ... } method in groovy so
buildType.doStuff1()
buildType.doStuff2()
buildType.doStuff3()
can be written as
buildType.with {
doStuff1()
doStuff2()
doStuff3()
}