How to Generate Buildconfigfield with String Type

How to generate buildConfigField with String type

String type build config fields should be declared like this:

buildConfigField "String", "SERVER_URL", "\"http://dev.myserver.com\""

the field name in quotes, the field value in escaped quotes additionally.

Android BuildConfig Field generating String incorrectly

After writing this I have found the way, it seems that the values are printed in the same way they are defined so if you add escaped quotation marks to this it will work, example:

buildTypes {
release {
minifyEnabled false
buildConfigField("String", "PARSE_APP_ID", '"xxxxxxxxxxxxxxxxxxxxxxxx"')
buildConfigField("String", "PARSE_CLIENT_ID", '"xxxxxxxxxxxxxxxxxxxxxxxxx"')
buildConfigField("String", "FACEBOOK_APP_ID", '"999999999999999"')
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}

After that, Rebuild and it will print the Strings values correctly:

public final class BuildConfig {
....
// Fields from build type: debug
public static final String FACEBOOK_APP_ID = "999999999999999999";
public static final String PARSE_APP_ID = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
public static final String PARSE_CLIENT_ID = "xxxxxxxxxxxxxxxxxxxxxxxx";
}

How to define a shared build variable?

You can put your common buildConfigField in defaultConfig:

android {
defaultConfig {
buildConfigField "string", "SHARED_URL", "https://stackoverflow.com/"
}

buildTypes {
debug {
buildConfigField "string", "PRIVATE_URL", "https://debugoverflow.com/"
}
release {
buildConfigField "string", "PRIVATE_URL", "https://releaseoverflow.com/"

proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

SHARED_URL will now be available for all build variants.

Gradle buildConfigField with integer variable

I found a solution, so maybe this answer will help somebody in future.

def String globalVersionCode

defaultConfig {
applicationId "com.test.gradle.build"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "0.1"

globalVersionCode = versionCode
}

buildTypes {
release {
buildConfigField ("int", "DatabaseVersion", globalVersionCode)
}
}

And now in java I can get DatabaseVersion variable:

public static final int DB_VERSION = BuildConfig.DatabaseVersion;

Define buildConfigField for androidTest

You have to pass it as a parameter to connectedAndroidTest task.

android {
...
buildTypes {
prod {
buildConfigField "String", "BASE_URL", "\"${getBaseUrl("abc.com")}\""
}
debug {
buildConfigField "String", "BASE_URL", "\"${getBaseUrl("efg.com")}\""
}
}
}

def getBaseUrl(String fallback) {
return project.hasProperty("base_url") ? project.getProperties().get("base_url") : fallback
}

Then passing parameters via -P:

./gradlew connectedDebugAndroidTest -Pbase_url="xxx.com"
./gradlew connectedProdAndroidTest -Pbase_url="yyy.com"

Gradle buildConfigField: Syntax for arrays & maps?

For array

app.gradle

        buildConfigField "String[]", "URL_ARRAY",
"{" +
"\"http:someurl\"," +
"\"http:someurl\"," +
"\"http:someurl\"" +
"}"

For Map

        buildConfigField "java.util.Map<String, String>", "NAME_MAP", 
"new java.util.HashMap<String, " +
"String>() {{ put(\"name\", \"John\"); put(\"name1\", \"John\"); put(\"name2\", " +
"\"John\"); }}"

Access in code:

HashMap<String, String> name = (HashMap<String, String>) BuildConfig.NAME_MAP;

buildConfigField for collection by reading .properties file

I created gradle function in order to generate texted-inline-function.

The example.properties assumes the data types are in <String, Boolean> pair.

example.properties

example1 = true
example2 = false

gradle function

android {
defaultConfig {
// read file from project root folder
buildConfigField 'java.util.Hashtable<String, Boolean>', 'PropertyPairs', makePropertyHashTable(getRootDir().getPath() + File.separator + 'example.properties')
}
}

def makePropertyHashTable(filename) {
def devProperties = new Properties()
try {
devProperties.load(new FileInputStream(file(filename)))
} catch (FileNotFoundException e) {
devProperties = null
System.out.println('devProperties value is null')
}

// result example: new Hashtable<String, Boolean>(){{ put(true, "a"); }};
def prefix = 'new java.util.Hashtable<String, Boolean>(){{ '
def suffix = '}}'
def value = ''
if (devProperties != null) {
for (d in devProperties) {
value += String.format('put("%s",%s); ', d.key, d.value)
}
}
}
return String.format('%s%s%s', prefix, value, suffix)
}

In application code usage

if (BuildConfig.PropertyPairs.getOrDefault("example1", false) == true) {
// do something
}

buildConfigField not working after updating gradle to 7.0.3

It's unclear how the build tools determine the order of the field declarations in the BuildConfig. What works though is this (note the BuildConfig.BACKEND_HOST instead of just BACKEND_HOST):

buildConfigField 'String', 'BACKEND_HOST', 'my.backend.host.com'
buildConfigField 'String', 'APPLICATION_LIST_URL', 'BuildConfig.BACKEND_HOST + "/page"'

Chapter 8.3.3 of https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html explains what forward references are legal and which ones are illegal.

Here's a minimal code sample showing how the BACKEND_HOST can be defined in each flavor:

    defaultConfig {
applicationId "com.example.myapplication"
minSdk 30
targetSdk 31
versionCode 1
versionName "1.0"

buildConfigField 'String', 'APPLICATION_LIST_URL', 'BuildConfig.BACKEND_HOST + "/page"'
}

flavorDimensions "version"
productFlavors {
free {
dimension "version"
buildConfigField "String", "BACKEND_HOST", '"www.free.com"'
}
paid {
dimension "version"
buildConfigField "String", "BACKEND_HOST", '"www.paid.com"'
}
}

This works because more specific BuildConfig fields (flavors) are evaluated first before the less specific ones (defaultConfig).

This code is copied from the OP's question and modified to compile by making the references to BACKEND_HOST static:

    defaultConfig {
applicationId "my.app.id"
minSdkVersion 21
versionCode getBuildTimestamp()
versionName "2.0.0"

buildConfigField 'String', 'APPLICATION_LIST_URL', 'BuildConfig.BACKEND_HOST + "/page"'
buildConfigField "String", "BACKEND_HOST", '"www.paid.com"'
}

flavorDimensions "type"
productFlavors {
local {
dimension "type"
targetSdkVersion 30
buildConfigField 'String', 'APK_DOWNLOAD_RESOLVE_URL', 'BuildConfig.BACKEND_HOST + "DOES_NOT_EXIST"'
}

remote {
dimension "type"
targetSdkVersion 30
applicationIdSuffix ".remote"
buildConfigField 'String', 'APK_DOWNLOAD_RESOLVE_URL', 'BuildConfig.BACKEND_HOST + "/remote/download"'
}
}

def backendRemote= '"https://myUrl"'

android.applicationVariants.all {
variant ->
def backendHost = backendRemote
variant.buildConfigField "String", "AUTH_HOST", backendHost
variant.buildConfigField "String", "BACKEND_HOST", backendHost
}

Android Studio gradle buildConfigField setup

That could be defined in any of the gradle.properties files:

  • In the module root
  • In the project root
  • In the Gradle home (e.g., ~/.gradle on Linux and macOS)

There's also a syntax for using environment variables to inject values like that, but that approach didn't use to work with Android Studio, and I am not aware that it now does. It would work for command-line builds (e.g., CI servers).

I think that there is a command-line switch approach as well for defining properties like these.

Personally, I use gradle.properties.



Related Topics



Leave a reply



Submit