In Android Gradle build.gradle What is "it" in it.buildConfigField? - android

I have search Gradle official website and Android Developer official website, but could not find an answer to this.
In android build.gradle, what is the "it." in the below buildConfigField method? Is this an instance of an object?
I found that moving the buildConfigField method up to defaultConfig lets me use the method without the "it."
What is the difference between the two? Why might I use one method over the other?
android {
...
defaultConfig {
...
buildConfigField 'String', 'API_KEY', MyApiKey
}
buildTypes {
release {
...
}
}
buildTypes.all {
...
}
buildTypes.each {
...
it.buildConfigField 'String', 'API_KEY', MyApiKey
}
}

Gradle build scripts are enhanced Groovy scripts. When you see "it" in a Groovy script or a Gradle build script, it represents the object that was passed into a closure. In your example, the closure is the "{...}" that was passed to "each". So, it iterates through the "buildTypes" collection (or something that is iterable), passes each entry to the closure, and you referenced the passed object as "it". You can change the name of the object passed to the closure, but it's "it" by default.

Related

Link Firebase for each build types

I have 3 mode of build types- debug, stage, release.
FCM, Firebase analytics had been integrated on my app.
My goal is to link different Firebase projects in each mode of my build.
As an example, if I build my app in stage mode, then Firebase project project_stage should be linked to my app, so all firebase settings should be worked with project_stage.
If I do some action, then analytics will be logged to project_stage, and I would need to get notification from project_stage.
Same for project_live and project_debug.
I have tried several ways but didn't work for me.
Pass the desired name as buildConfigField FIREBASE_APP_NAME or R.string.firebase_app_name:
android {
// default configuration, don't touch.
defaultConfig {
buildConfigField "String", "FIREBASE_APP_NAME", "\"default\""
resValue("string", "firebase_app_name", "default")
}
buildTypes {
debug {}
staging {}
release {}
}
sourceSets {
main {} // default source-set
foo {}
bar {}
}
productFlavors {
foo {
buildConfigField "String", "FIREBASE_APP_NAME", "\"foo\""
resValue("string", "firebase_app_name", "foo")
}
bar {
buildConfigField "String", "FIREBASE_APP_NAME", "\"bar\""
resValue("string", "firebase_app_name", "bar")
}
}
}
One can likely either configure productFlavors or buildTypes, unless combining app names. However, then one can instance FirebaseApp with the name inside the application package:
FirebaseApp.getInstance(BuildConfig.FIREBASE_APP_NAME);
Or with string resource:
FirebaseApp.getInstance(getString(R.string.firebase_app_name));
There's also an android.environments Gradle plugin for generating these buildConfigField.
Likewise, one could just use a string resource in the proper res directory. When configuring productFlavors and sourceSets with the same names (and obviously also the corresponding directories & files), one can configure all the rest with string resources, instead of Android DSL.
Gradle sourceSets permit for more than just alternate string resources ...

Is it possible "def" value in build.gradle file

I am generating multiple apk's based on different config files.
So i defined a variable on build.gradle file
def isPRODBuild = false
I want to change this variable in productFlavors scope, so i did following.
productFlavors {
dev {
isPRODBuild= false
}
prod {
isPRODBuild= true
}
}
But it seems like that its not changing the value of isPRODBuild value.
Do in need to use some other type of variable in build.gradle file?
At build time, Gradle generates the BuildConfig class so your app code
can inspect information about the current build. You can also add
custom fields to the BuildConfig class from your Gradle build
configuration file using the buildConfigField() method and access
those values in your app's runtime code. Likewise, you can add app
resource values with resValue().
So you could simply use buildConfigField to define your variable.
productFlavors {
dev {
buildConfigField "boolean", "isPRODBuild", "false"
}
prod {
buildConfigField "boolean", "isPRODBuild", "true"
}
}
Then to access the aforementioned variable simply use BuildConfig.isPRODBuild

Is here anyway to access gradle ext properties in java code?

This is project level gradle.build file:
buildscript {
ext {
server_test = 'http://192.618..'
server_main = "https://68.5..."
another_value = "test"
}
ext.kotlin_version = '1.3.41'
....
....
I'm using these values in my app level gradle.build file.
Is there ay way to access these variables in my Java Project files also!.
if you are trying to explicitly access gradle extensions in java code, the answer is no: it's not possible, see this : Android - Read build.gradle properties inside class, and also see this Is it possible to declare a variable in Gradle usable in Java?
using buildConfigFields in gradle (app level, not root level), you can :)
buildConfigField "String", "variable_name", "variable_value"
as a complete example :
productFlavors {
dev {
dimension "your_dimension_name"
buildConfigField "String", "SERVER_TEST", "\"http://192.618..\""
buildConfigField "String", "SERVER_MAIN", "\"https://68.5...\""
buildConfigField "String", "ANOTHER_VALUE", "test"
}
you can then access these variables throughout your project by using :
BuildConfig.SERVER_TEST
Have a look at this link for a more complete answer if this didn't help :
How to generate buildConfigField with String type

BuildConfigField mock for unit test in Kotlin

I'm trying to cover as much as possible a Kotlin Android library and I'm encountering an issue about custom BuildConfig variable, better known as buildConfigField.
I would like to mock this variable to test both true and false values.
Extract from Gradle file :
android {
defaultConfig {
buildConfigField "boolean", "ENABLE_LOG", "false"
}
flavorDimensions "log"
productFlavors {
loggable {
buildConfigField "boolean", "ENABLE_LOG", "true"
dimension "log"
}
notloggable {
dimension "log"
}
}
}
Extract of the Kotlin function to be tested :
fun buildClient(): MyClient {
var myClientBuilder : MyClient.Builder = MyClient.Builder();
if (BuildConfig.ENABLE_LOG) {
val interceptor = LoggingInterceptor();
interceptor.setLevel(LoggingInterceptor.Level.ALL);
myClientBuilder.addInterceptor(interceptor);
}
return myClientBuilder.build()
}
Unit test :
#Test
fun buildClient_enableLog_oneInterceptor() {
// GIVEN
Mockito.mock(BuildConfig::class.java)
Mockito.doReturn(true).`when`(BuildConfig.ENABLE_LOG)
// WHEN
val myClient = myService!!.buildClient()
// THEN
assertNotNull(myClient)
assertNotNull(myClient.interceptors())
assertEquals(1, myClient.interceptors().size)
}
I tried different things and it never works.
If someone have already done this work, it can help me a lot (and others I guess).
Thanks
ReflectionHelpers.setStaticField(BuildConfig::class.java, "ENABLE_LOG", true)
By default, all tests run against the debug build type. You can change this to another build type by using the testBuildType property in your module-level build.gradle file. For example, if you want to run your tests against your "staging" build type, edit the file as shown in the following snippet.
android {
...
testBuildType "staging"
}
but this is causing other options to fail
Little late to the party but this is how you should test any thing related to BuildConfig file.
BuildConfig.java is generated for each variant of your app. In your case you have atleast 4 variants.
LoggableDebug
LoggableRelease
NotloggableDebug
NotloggableRelease
ENABLE_LOG will be false for options 3 and 4.
If you want to Unit test this, I recommend writing UnitTest in src/testNotLoggable/java/com/.../TestFile.java.
In that TestFile.java your BuildConfig.ENABLE_LOG should be false.
You can check BuildConfig.java file for each variant under /build/source/buildConfig/flavorname/debug/com/project/../BuildConfig.java

Build string into Android .apk but keep out of source control

How do I take an environment variable at build-time and make it available as R.string.api_key at app runtime?
A typical pattern is to put the string in gradle.properties:
API_KEY=whatever-it-is
If you really want it to be a string resource, you can then use resValue in build.gradle:
defaultConfig {
// other stuff here
resValue "string", "api_key", API_KEY
}
(as values in gradle.properties get exposed as global variables to your Gradle script)
Or, if you need the value in Java code, you could use buildConfigField:
defaultConfig {
// other stuff here
buildConfigField "String", "API_KEY", '"'+API_KEY+'"'
}
then reference it as BuildConfig.API_KEY.
And, of course, do not check gradle.properties into version control.

Categories

Resources