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()
}
Related
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)
}
Here's an extremely simplified version of what I'm trying to do in Gradle for my Android app:
android {
buildTypes {
debug {
buildConfigFieldMyWay("keyName", "keyValue")
buildConfigField("String", "keyName", "keyValue") }
}
}
}
def buildConfigFieldMyWay(String keyName, String keyValue) {
buildConfigField("String", keyName, keyValue)
}
The real version is more complex, which is why it would be nice to organize what I'm doing into separate functions.
The problem is that when I do a Gradle sync, I get this error:
No signature of method: build_byqgds5lao5ipgp4gk5ftyud4.android() is applicable for argument types: (build_byqgds5lao5ipgp4gk5ftyud4$_run_closure2) values: [build_byqgds5lao5ipgp4gk5ftyud4$_run_closure2#536e468e]
I think this has to do with the DSL Gradle uses with Android; that when buildConfigField() is called inside of android { buildTypes { debug, that it is running buildConfigField() on a BuildType object. If I call it from a separate function, there is no BuildType for it to operate on.
So I either need to modify the DSL so that my function (buildConfigFieldMyWay()) can be called in android { buildTypes { debug and operate on the BuildType object, or I need to pass the BuildType to the function. There's likely some simple syntax I need to use here that I'm not finding. What is it?
You can pass the build type inside the function buildConfigFieldMyWay:
def buildConfigFieldMyWay(buildType, String keyName, String keyValue) {
buildType.buildConfigField("String", keyName, keyValue)
}
And then, you can get the build type using it:
android {
buildTypes {
debug {
buildConfigFieldMyWay(it, "keyName", "keyValue")
buildConfigField("String", "keyName", "keyValue")
}
}
}
To disable generating BuildConfig with the Groovy DSL, one could do the following:
afterEvaluate {
generateReleaseBuildConfig.enabled = false
generateDebugBuildConfig.enabled = false
}
I am trying to find the equivalent when using Gradle's Kotlin DSL (build.gradle.kts). Anyone have any luck with this?
If you have Android Studio 4.1 or greater you can use the Build Features Field to disable it per module.
android {
...
buildFeatures {
buildConfig = false
resValues = false
}
}
I ended up finding this to work as well:
android { ... }
tasks.withType<GenerateBuildConfig> {
isEnabled = false
}
You can remove BuildConfig from all variants by adding the following:
For library
android {
...
// TODO replace with https://issuetracker.google.com/issues/72050365 once released.
libraryVariants.all {
generateBuildConfigProvider?.get()?.enabled = false
}
}
For application
android {
...
// TODO replace with https://issuetracker.google.com/issues/72050365 once released.
applicationVariants.all {
generateBuildConfigProvider?.get()?.enabled = false
}
}
If you want to specify a build type , then:
libraryVariants
.matching { it.buildType.name == "release"}
.all {
generateBuildConfigProvider?.get()?.enabled = false
}
}
I would like to launch my Android app in such a way that I can set some external variable that my app can read. It would be nice if this was possible either in Gradle or as part of the debug/run configuration.
In essence, I would like to test for a variable to see if it is set. In this example I would like to set USE_FAKE_DATA:
if (USE_FAKE_DATA) {
...
} else {
...
}
One way is to use build variants and I have done this before. But I'm wondering if another way has been made available.
Gradle File
android {
buildTypes {
debug {
buildConfigField "boolean", "USE_FAKE_DATA", "true"
}
release {
buildConfigField "boolean", "USE_FAKE_DATA", "false"
}
}
}
Java File
class Test extends Activity {
#Override
public void onCreate(Bundle data) {
if (BuildConfig.USE_FAKE_DATA) {
...
} else {
...
}
}
}
Please refer this answer for more.
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)