I am developing in Android, and I have a submodule in my project.
I have set buildConfigField like the following in build.gradle of Module
buildTypes {
release {
minifyEnabled false
buildConfigField "String", "TestId", '"48"'
}
dev {
buildConfigField "String", "TestId", '"88"'
}
}
And I use TestId in module.
But I want to change the TestId from outside, like build.gradle of app.
How to set the buildConfigField of module from build.gradle of app for Android ?
Thanks in advance.
Your question is a little confusing for me. I don't really get your point. But I want to point out. The buildConfigField will generate corresponding field in BuildConfig. And these fields are decorated by final keyword. So they can't be changed.
Related
We have an App in Kotlin ( Android Stdio) which has different constants by environment.
We are using Constants.kt
const val IMAGES_API = "https://localhost:3000/v1/images"
and we want to use the same variable in staging/qa/prod.
The App is building in Kotlin and we are using gradle (groovy scripts) to compiling and packing the different environment staging/qa/prod.
My first approach has been to create this properties on the gradle.properties and load the properties on the build.gradle file like this :
def loadProperties() {
def props = new Properties()
file("gradle.properties").withInputStream { props.load(it) }
def config = props
project.ext.config = config
}
And when I run gradle I can see the new properties, but I don't know how to get this value inside the App ( in the kotlin code).
My only idea is to create a task on build.gradle to copy a Constants.kt file by environment. But, I don't think, it's a good practice. I think, there must be another way to set different variables in the App.
Please, can anybody help me with this?
What you want is to configure build types in your app module's gradle file with buildConfigField in each:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
buildConfigField "String", "SERVER_URL", '"http://prod.this-is-so-fake.com"'
}
debug {
applicationIdSuffix ".debug"
debuggable true
buildConfigField "String", "SERVER_URL", '"http://test.this-is-so-fake.com"'
}
/**
* The `initWith` property allows you to copy configurations from other build types,
* then configure only the settings you want to change. This one copies the debug build
* type, and then changes the application ID.
*/
staging {
initWith debug
applicationIdSuffix ".debugStaging"
buildConfigField "String", "SERVER_URL", '"http://prod.this-is-so-fake.com"'
}
}
In code, you can refer to BuildConfig.SERVER_URL, and it will be populated with the string based on the build type you choose at compile time.
You can build different apk/app bundles to distribute.
Referencing this answer .
EDIT As an aside, in real life I have found this approach to be... annoying. It is easier to bundle inside the app a toggle that allows QA to switch between environments. This way you only have one bundle to deal with.
I want to assign a value to a string in string.xml different values depending on the Build Variant/buildType. I imagine something like this:
res/values-debug/string.xml
<string name="my_string">some debug value</string>
res/values-release/string.xml
<string name="my_string">some release value</string>
but I don't see anything like this out there.
Is this possible?
It possible via your build.gradle file
buildTypes {
release {
resValue "string", "my_string", "some release value"
}
debug {
resValue "string", "my_string", "some debug value"
}
}
Then you can just use this value like #string/my_string where you want
Yes it's possible!
In your build.gradle you can add something like this:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
signingConfig signingConfigs.release
}
debug {
applicationIdSuffix ".debug"
minifyEnabled false
debuggable true
signingConfig signingConfigs.release
}
}
Then in your src folder in your project you should have a folder called main, add one next to it called debug. Den as long as you are building your debug flavour any resources in your debug folder will replace those in main which is the release folder.
Should look like this:
src/
main/
java/ -- all your java code
res/
...
values/
strings.xml
debug/
res/
...
values/
strings.xml
EDIT: The approaches from the two other answers works fine as well. But if you have a lot of strings keeping them as xml might be easier to handle.
resValue 'string', '<string_name>', "some string"
define different ones in your build.gradle for different build variants/product flavors
You can do it directly from Android Studio. For example, if you need a different app name for your "staging" flavor, you can (Android Studio v3.5):
Right click on values folder -> New -> Values resource file
Select "staging" in the source set menu
specify strings.xml as filename
At this point Android Studio generates an additional strings.xml file for your particular build variant. Edit the created file with your "staging" app name (E.g. MyAppName - Staging)
build.gradle(app)
productFlavors {
stage {
applicationIdSuffix ".staging"
buildConfigField 'String', 'SITE_URL', '"[staging_link_here]"'
}
prod {
buildConfigField 'String', 'SITE_URL', '"[production_link_here]"'
}
}
The resValue method (or whatever it's called) allows you to set a resource value in buildTypes or productFlavors. Is there a corresponding way to get a resource value that was set by resValue?
It appears that productFlavors is evaluated before buildTypes, so a resValue set in buildTypes takes precedence. I want to append "Debug" to the app name in debug builds, but I need to get the value that was set in the product flavor in order to append to it.
Edit: I tried Marcin KoziĆski's suggestion to use a variable, but all product flavors are evaluated before any build type. Therefore, this does not work:
android {
String appName = ""
productFlavors {
Foo {
appName = "Foo"
}
Bar {
appName = "Bar"
}
}
buildTypes {
release {
resValue "string", "app_name", appName
}
debug {
resValue "string", "app_name", appName + " Debug"
}
}
}
In buildTypes, appName always has the value from the last product flavor. So in this example, all builds receive the name "Bar" or "Bar Debug".
Basically, I need a resValueSuffix analogous to applicationIdSuffix. Apparently no such animal exists. Does the com.android.application plugin expose anything that I could use to achieve this?
If you are only trying to set the App Label (or other manifest values) you can solve this with manifest placeholders.
android {
productFlavors {
Foo {
applicationId "com.myexample.foo"
manifestPlaceholders.appName = "Foo"
}
Bar {
applicationId "com.myexample.bar"
manifestPlaceholders.appName = "Bar"
}
}
buildTypes {
release {
manifestPlaceholders.appNameSuffix =""
}
debug {
manifestPlaceholders.appNameSuffix =".Debug"
applicationIdSuffix ".debug"
}
}
}
Then in your Android Manifest you simply use both placeholders for your app name (or other values)
<application
android:label="${appName}${appNameSuffix}"
...
</application>
This allow you to install all 4 variants side by side on a single device as well as give them different names in the app drawer / launcher.
EDIT 11/22/2019
Updated how placeholders values are set based on feedback from #javaxian
You can check the build variants like this
Define values in gradle
buildTypes {
debug{
buildConfigField "String", "Your_string_key", '"yourkeyvalue"'
buildConfigField "String", "SOCKET_URL", '"some text"'
buildConfigField "Boolean", "LOG", 'true'
}
release {
buildConfigField "String", "Your_string_key", '"release text"'
buildConfigField "String", "SOCKET_URL", '"release text"'
buildConfigField "Boolean", "LOG", 'false'
}
}
And to access those values using build variants:
if(!BuildConfig.LOG)
// do something with the boolean value
Or
view.setText(BuildConfig.yourkeyvalue);
To have an alternative version of a resource in debug builds you can use the debug source set.
strings.xml can be found under following path src/main/res/values, which means it's in the main source set. If you create a new directory src/debug/res/values you can put a new strings.xml file in there with values that should be overridden in debug builds. For example:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My Application Debug</string>
</resources>
This will replace whatever value app_name has in your main file. You don't have to duplicate all the strings in here - ones you don't include here are simply taken from the main file.
How to use a property from gradle.properties inside android activity? Whenever I build the code it throws error. Is there a particular way that the properties can be accessed inside the activities?
You can't access the gradle.properties from your Activity.
The gradle.properties is used while you are building the app, it doesn't exist in runtime or inside your apk.
However you can set some values inside the BuildConfig class from your build.gradle script (reading from the gradle.properties for example).
Just use somenthing like:
buildConfigField "boolean", "MY_FLAG", "true"
buildConfigField "String" , "MY_KEY" , "\"XXXXX-XXXXX-XXX\""
in gradle.properties:
SIMPLE_STRING=ABC
in build.gradle:
android {
buildTypes {
debug {
buildConfigField 'boolean', 'PREPROD', 'true'
buildConfigField "String" , "MY_KEY" , SIMPLE_STRING
}
}
}
you can use buildConfigField
for example:
android {
buildToolsVersion "22.0.1"
defaultConfig {
buildConfigField "String", "USED_TOOLS", "\"${android.getBuildToolsVersion()}\""
}
}
will add field USED_TOOLS to your application BuildConfig.java
public static final String USED_TOOLS = "22.0.1";
This question already has an answer here:
Is there a way to have a common section with buildConfigField and resValue in gradle?
(1 answer)
Closed 7 years ago.
I have a number of flavors in my app, and I want to set a boolean buildConfigField for a subset of them. Is there a way to avoid having to add the field to every flavor? Ideally my build.gradle would look like the following:
productFlavors {
flavor1 {
}
....
flavor4 {
buildConfigField "boolean", "DISABLE_SOMETHING", "true"
}
flavor5 {
buildConfigField "boolean", "DISABLE_SOMETHING", "true"
}
....
flavor8 {
}
}
So in my app I can just go
if (BuildConfig.DISABLE_SOMETHING) {
//disable stuff
}
However, compilation fails when I try to build with, for example, flavor1, as it can't find the field. I don't want to have to remember to add this to every new flavor I create. Are there any ways around this?
You can use defaultConfig for this (inside android{})
defaultConfig {
buildConfigField "boolean", "DISABLE_SOMETHING", "true"
}