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"
}
Related
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.
I want to create an application with two flavours one with less features and one with more. How can i do it
Let us suppose there is
A - application
Flavour1 - feature1, feature2
Flavour2 - feature1, feature2, feature3
How to release one apk
and how user will install the application from play store how the user will know which flavour is going to be installed
There is nice documentation from google.
Multiple flavours
You should declare the flavors in the buildfile
android {
...
defaultConfig {...}
buildTypes {...}
productFlavors {
demo {
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
}
full {
applicationIdSuffix ".full"
versionNameSuffix "-full"
}
}
}
After build two apk files will be created. They have different application id so you can publish them as two different applications to the Play Store. For example one free and one paid.
Features
There can be more solutions but the simplest one is to use buildConfigField.
productFlavors {
demo {
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
buildConfigField "boolean", "FEATURE_1", "true"
buildConfigField "boolean", "FEATURE_2", "false"
buildConfigField "boolean", "FEATURE_3", "false"
}
full {
applicationIdSuffix ".full"
versionNameSuffix "-full"
buildConfigField "boolean", "FEATURE_1", "true"
buildConfigField "boolean", "FEATURE_2", "true"
buildConfigField "boolean", "FEATURE_3", "true"
}
}
Then in java source code you can check if features are enabled:
if (BuildConfig.FEATURE_1) {
//run feature
}
Some othe approaches are described in the documentation.
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";
I'm trying to work with build flavors. In my build.gradle I've defined 2 flavors, a normal flavor and an admin flavor.
Basicly, the admin flavor has an extra button on the main activity.
I understand that I can define different packages/classes for different flavors. But is there a way to make a sort of if case to add/remove a piece of code depending on the flavor?
Basicly, I would need two versions of an Activity. But I don't want two entire different versions of the activity and maintain them.
So in my activity I would like to do
=> gradle check if flavor is 'admin'
=> if yes, add this code of the button
Is this possible? Or would you need two different physical activities and thus maintain both of them when you add functionality afterwards.
BuildConfig.FLAVOR gives you combined product flavor.
So if you have only one flavor dimension:
productFlavors {
normal {
}
admin {
}
}
Then you can just check it:
if (BuildConfig.FLAVOR.equals("admin")) {
...
}
But if you have multiple flavor dimensions:
flavorDimensions "access", "color"
productFlavors {
normal {
dimension "access"
}
admin {
dimension "access"
}
red {
dimension "color"
}
blue {
dimension "color"
}
}
there are also BuildConfig.FLAVOR_access and BuildConfig.FLAVOR_color fields so you should check it like this:
if (BuildConfig.FLAVOR_access.equals("admin")) {
...
}
And BuildConfig.FLAVOR contains full flavor name. For example, adminBlue.
To avoid plain string in the condition, you can define a boolean property:
productFlavors {
normal {
flavorDimension "access"
buildConfigField 'boolean', 'IS_ADMIN', 'false'
}
admin {
flavorDimension "access"
buildConfigField 'boolean', 'IS_ADMIN', 'true'
}
}
Then you can use it like this:
if (BuildConfig.IS_ADMIN) {
...
}
You can define either different build configuration fields or different resource values (like string values) per flavor, e.g. (as per Google's gradle tips and recipes), e.g.,
android {
...
buildTypes {
release {
// These values are defined only for the release build, which
// is typically used for full builds and continuous builds.
buildConfigField("String", "BUILD_TIME", "\"${minutesSinceEpoch}\"")
resValue("string", "build_time", "${minutesSinceEpoch}")
...
}
debug {
// Use static values for incremental builds to ensure that
// resource files and BuildConfig aren't rebuilt with each run.
// If they were dynamic, they would prevent certain benefits of
// Instant Run as well as Gradle UP-TO-DATE checks.
buildConfigField("String", "BUILD_TIME", "\"0\"")
resValue("string", "build_time", "0")
}
}
}
So in this case, something like
productFlavors {
normal {
dimension "access"
buildConfigField("boolean", "IS_ADMIN", "false")
}
admin {
dimension "access"
buildConfigField("boolean", "IS_ADMIN", "true")
}
}
and then use it like
if (BuildConfig.IS_ADMIN) {
...
} else {
...
}
or if it is just to have different string values for different flavors, it can be done with different resValues and then you don't even need the if/then
You can try this way
productFlavors {
def app_name = "you app name"
development {
versionCode 1
versionName "1.0.1"
buildConfigField 'String', 'varibalename', ""
}
release {
versionCode 1
versionName "1.0.1"
buildConfigField 'String', 'varibalename', ""
}
}
if(BuildConfig.varibalename){}