After I set up productFlavors for my app, three new folders appear with the build variants. My app still works but I don't know why it appears and how to clear them
This is my productFlavors code
productFlavors {
Dev {
buildConfigField("String", "BASE_URL", "\"https://foo_dev/api/\"")
buildConfigField("String", "BASE_URL_IMAGE", "\"https://foo_dev/\"")
}
QA {
buildConfigField("String", "BASE_URL", "\"https://foo_qa/api/\"")
buildConfigField("String", "BASE_URL_IMAGE", "\"https://foo_qa/\"")
}
}
Related
In my application I have 4 environments i.e Dev, SIT, UAT, Release. For each environment I have a build type with it's own configuration. Much like the suggested way, e.g:
buildTypes {
Dev {
buildConfigField "String", 'BASE_URL', "https://dev-api.yourbackend.com"
}
SIT {
buildConfigField "String", 'BASE_URL', "https://sit-api.yourbackend.com"
}
UAT {
buildConfigField "String", 'BASE_URL', "https://uat-api.yourbackend.com"
}
Release {
buildConfigField "String", 'BASE_URL', "https://api.yourbackend.com"
}
}
But now I have 5-6 different such configurations, not just the BASE_URL. Like ClientId, ClientSecret etc..
Plus I have 2 product flavours, meaning I need to create 8 different build variants and have all these 5-6 configurations inside each such variant. All that looks clumsy.
1 other solution I found is to create a folder for each of the build variant like flavour1Dev, flavour2Sit, flavour2Uat etc.. and have the config file specific to that variant inside that folder. This again involves 8 different folders and keeps growing as we add more environments.
Is there a better way of handling this, probably like a config.gradle file where I can only have these configurations and import it back in the app/build.gradle, a way of modularising the whole build variant configurations.
Update-1
I tried this as per #Md. Asaduzzaman's Answer:
build.gradle
…
…
apply from: './config.gradle'
…
…
android {
…
…
defaultConfig {
…
…
buildConfigField('String', ‘BASE_URL’, '"https://default.yourbackend.com”')
}
…
…
}
config.gradle
android {
buildTypes {
dev {
buildConfigField('String', ‘BASE_URL’, '"https://dev.yourbackend.com”')
}
sit {
buildConfigField('String', ‘BASE_URL’, '"https://sit.yourbackend.com”')
}
}
}
The issue is that in the generated BuildConfig, I still see the default values:
public static final String BASE_URL = "https://default.yourbackend.com";
You already mentioned the solution yourself by creating separate config.gradle file. I try to implement it like below:
Step - 1: Create config.gradle inside your app folder and add all the configurations.
android {
buildTypes {
Dev {
buildConfigField "String", 'BASE_URL', "https://dev-api.yourbackend.com"
}
SIT {
buildConfigField "String", 'BASE_URL', "https://sit-api.yourbackend.com"
}
UAT {
buildConfigField "String", 'BASE_URL', "https://uat-api.yourbackend.com"
}
Release {
buildConfigField "String", 'BASE_URL', "https://api.yourbackend.com"
}
}
productFlavors {
flavor1 {
/*implementation*/
}
flavor2 {
/*implementation*/
}
flavor3 {
/*implementation*/
}
}
}
Step -2: Include the config.gradle in your app/build.gradle.
apply plugin: 'com.android.application'
apply from: './config.gradle'
....
We have a white label application with a handful of flavors for different clients. A new client has come on that wants the ability to publish the app through their own developer account. However, prior to release, we need to test the app through our internal test track and verify that the prod environment works (such as billing).
When we got started with development, we created a new product flavor, "com.business.android.product". Now that we are getting close to release, we need a different package name, "com.example.android.thing". My question is, how can we have two package names for the same flavor (i.e. using the same code in the /product source folder)?
Here is an example of our flavor and build type setup
productFlavors {
prod1 {
applicationId "com.business.android"
buildConfigField 'boolean', 'REPORT_CRASHES', "true"
}
prod2 {
applicationId "com.business.android.product2"
buildConfigField 'boolean', 'REPORT_CRASHES', "true"
}
prod3 {
applicationId "com.business.android.product3"
buildConfigField 'boolean', 'REPORT_CRASHES', "true"
def flavor = "spg"
}
prod4 {
applicationId "com.company.android.product4"
buildConfigField 'boolean', 'REPORT_CRASHES', "true"
}
/* Need a way to have all the code in /prod4 flavor source folder but with
* a very different applicationId - ex. somebusiness.android.product4
*
*/
}
buildTypes {
debug {
debuggable true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.KEY
def buildType = "debug"
def targetEnvironment = "production"
buildConfigField "boolean", "PRODUCTION_ENV", "true"
}
debugTst {
minifyEnabled false
debuggable true
signingConfig signingConfigs.KEY
def buildType = "debug"
buildConfigField "boolean", "PRODUCTION_ENV", "false"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.KEY
def buildType = "release"
buildConfigField "boolean", "PRODUCTION_ENV", "true"
}
releaseTst {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.KEY
def buildType = "release"
buildConfigField "boolean", "PRODUCTION_ENV", "false"
}
}
This issue can be resolved by performing the follow:
sourceSets {
prod4Ext.java.srcDirs += 'src/prod4/java'
prod4Ext.res.srcDirs += 'src/prod4/res'
}
This will provide the prod4 flavor's source code and layouts to the newly created flavor prod4Ext.
I want to modify the token and API urls from my java code so that I can create a development or release build depending on mode selected from my custom screen.
Below is the code used in build.gradle
productFlavors {
dev {
buildConfigField "String", "TOKEN_URL", '"https://example.com"'
buildConfigField "String", "API_URL", '"https://api.ex"'
versionCode getDevVersionCode()
}
prod {
buildConfigField "String", "TOKEN_URL", '"https://release.example2.com"'
buildConfigField "String", "API_URL", '"https://api.release.ex"'
versionCode getReleaseVersionCode()
}
}
first in app/build.gradle, add the productFlavor under android
productFlavors {
qa {
buildConfigField "boolean", "LOG_HTTP", "true"
}
staging {
buildConfigField "boolean", "LOG_HTTP", "true"
}
live {
buildConfigField "boolean", "LOG_HTTP", "false"
}
}
then you need to create specific directories in app/src directory
finally, you just create a same name File in these different directories, like the following picture
in each ServerConstants(the name can be arbitrate), you should reference specific variables of "TOKEN_URL" and "API_URL"
I have two environment of my project one Prod another one is Staging. So whenever I have to build any of the environment, I have to change multiple keys like map key, label name and other things in manifest. So I have searched and find out some of the solutions and manifestPlaceholders is one of them.
Now what I want to do is to assign multiple value in manifestPlaceholders. So can I put multiple values in it and yes then how to put multiple values in it. Here is the code for the manifestPlaceholders
buildTypes {
debug {
manifestPlaceholders = [ google_map_key:"your_dev_key"]
}
release {
manifestPlaceholders = [ google_map_key:"prod_key"]
}
}
I have solved my problem as below code by adding multiple manifestPlaceholders values. Added this to my module build.gradle.
productFlavors {
staging {
applicationId "xxxxxxxxxxx"
manifestPlaceholders = [ google_map_key:"xxxxxxxxxx", app_label_name:"xxxxxxx"]
buildConfigField 'String', 'BASE_URL', '"xxxxxxxxxx"'
}
prod {
applicationId "xxxxxxxxxxx"
manifestPlaceholders = [ google_map_key:"xxxxxxxxxx", app_label_name:"xxxxxxx"]
buildConfigField 'String', 'BASE_URL', '"xxxxxxxxxx"'
}
}
EDIT:
You can use resValue also as Emanuel Moecklin suggested in comments.
productFlavors {
staging {
applicationId "xxxxxxxxxxx"
manifestPlaceholders = [ google_map_key:"xxxxxxxxxx", app_label_name:"xxxxxxx"]
buildConfigField 'String', 'BASE_URL', '"xxxxxxxxxx"'
resValue "string", "base_url", "xxxxxxxxxx"
}
prod {
applicationId "xxxxxxxxxxx"
manifestPlaceholders = [ google_map_key:"xxxxxxxxxx", app_label_name:"xxxxxxx"]
buildConfigField 'String', 'BASE_URL', '"xxxxxxxxxx"'
resValue "string", "base_url", "xxxxxxxxxx"
}
}
You can easily set/change multiple manifestPlaceholders values. You can either define all values at once, as in your answer, or one by one.
defaultConfig {
// initialize more values
manifestPlaceholders = [ google_map_key:"xxxxxxxxxx", app_label_name:"xxxxxxx"]
// or this way
manifestPlaceholders.google_map_key = "xxxxxxxxxx"
manifestPlaceholders.app_label_name = "xxxxxxxxxx"
}
productFlavors {
staging {
}
prod {
// use some different value for prod
manifestPlaceholders.google_map_key = "yyyyyyyyyy"
}
}
I have mentioned for both build Types and flavors
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
resValue "string", "google_maps_key", "release google map key"
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
resValue "string", "google_maps_key", "debug google map key"
}
}
productFlavors {
alpha {
applicationId = "com.example.alpha"
resValue 'string', 'app_name', 'alphaapp'
resValue "string", "maps_api_key", "XXXXXXXXXXXXXXXXXXXXX"
}
beta {
applicationId = "com.example.beta"
resValue 'string', 'app_name', 'betaapp'
resValue "string", "maps_api_key", "XXXXXXXXXXXXXXXXXXXXXX"
}
}
I could not use the suggested approaches in other answers because gradle seems to have changed the type of manifestPlaceholders to val mutablemap in a recent release.
This was the only fix that worked for me:
manifestPlaceholders["key"] = "value0"
manifestPlaceholders["key"] = "value1"
Well, we can set manifestPlaceholders key values using the following ways,
select File > Project Strucutre
Add environment
2-1. select Flavors tab
2-2. Add flavor dimension and name for dimension ex."env"
2-3. Add product flavor an name product ex. "prod"
Add manifestPlaceHolder keys
3-1. Select the above product
3-2. Add key in Manifest Placeholders list
press OK
build.gradle file is automatic updated after press the buttton
I need to create different app names depending on the product flavour used.
While this was easy by simply setting a string resource, I can no longer do that because when the app is uploaded to hockeyapp the app name is set as '#string/app_name' instead of the value of app_name.
I have made some progress by setting the label in the manifest to be '${applicationName}' and setting the value with
manifestPlaceholders = [ applicationName : appName ];
in the product flavour block so that the value gets set at compile time.
The problem comes when I try to append the build type to the application name. I can't seem to find a way to know what build type is currently being used within the product flavour.
This is a stripped down version of the build for readability
android {
buildVersionName "1.0.0
buildTypes {
release {
... nothing special
}
uat {
signingConfig signingConfigs.debug
buildType = "uat"
applicationIdSuffix = "." + buildType
}
debug {
signingConfig signingConfigs.debug
buildType = "uat"
applicationIdSuffix = "." + buildType
}
}
productFlavors{
flavor1{
def appName = "app name " + buildType;
manifestPlaceholders = [ applicationName : appName ];
applicationId [id]
def clientIteration = [client iteration]
versionName buildVersionName + clientIteration
versionCode [version code]
}
flavor2{
... same as above with different app name
}
flavor3{
... same as above with different app name
}
}
}
This code works fine except the variable 'buildType' is always the last buildtype (in this case debug) which means the app name always has debug on the end.
Probably worth noting that I don't need to have anything appended on the end of the app name for releases.
You can append the values like this
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"
}
}
}
and in the manifest
<application
android:label="${appName}${appNameSuffix}"
...
</application>
If you want to access different values based on build type you can do it like this
buildTypes {
debug{
buildConfigField "String", "Your_string_key", '"yourkeydebugvalue"'
buildConfigField "String", "SOCKET_URL", '"some text"'
buildConfigField "Boolean", "LOG", 'true'
}
release {
buildConfigField "String", "Your_string_key", '"yourkeyreleasevalue"'
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);
I know I'm a bit late for the party but if you want different names based on the flavours, you should have something like this:
productFlavors{
flavour 1 {
applicationId "your_app_id"
resValue "string", "app_name", "Flavour 1 app name"
.......
}
flavour 2 {
applicationId "your_app_id"
resValue "string", "app_name", "Flavour 2 app name"
.......
}
}
and in your AndroidManifest.xml:
android:label="#string/app_name"
Hope this helps.
This link http://inaka.net/blog/2014/12/22/create-separate-production-and-staging-builds-in-android/ may help you out.
If you have two productFlavors (Production and Staging, for instance)
You should create two different resource folders:
project/app/src/production/res/values/strings.xml
<resources>
<string name="root_url">http://production.service.com/api</string>
</resources>
project/app/src/staging/res/values/strings.xml
<resources>
<string name="root_url">http://staging.service.com/api</string>
</resources>
You should add this following code inside the android {}:
productFlavors {
production {
applicationId "com.inaka.app.production"
}
staging {
applicationId "com.inaka.app.staging"
}
}
It's a good idea to have different icons for different productFlavors, just add the icon inside each different resource folder.