# [Android Product Flavor](https://developer.android.com/studio/build/build-variants.html#product-flavors)
###### tags: `Android Gradle`

[TOC]
# Introduction
With **Product Flavor**, we can have **many versions of the same app** with slightly different variables/aspects in each.
# Where to use it?
All Product Flavor settings are set in **build.gradle** file , which is located in **app/build.gradle**.
We can also put it in an apart .gradle file, while applying the file in the same **build.gradle (app/build.gradle)**.
**Example:**
```java=
apply from: '../variant.gradle'
```
>[color=lightgreen]
# How to set up?
Having **build.gradle (app/build.gradle)** opened, we can either set it up on the **same file** or get a **separated .gradle file**
## Things to take into account before set up
No matter either set up in build.gradle or separated .gradle file, all set ups must:
1. **be enclosed by android {}**
2. **specify flavorDimension "inputName"
**Example:**
```java=
android {
flavorDimensions "productFlavor"
productFlavors {
flavor {
}
flavor1 {
}
}
}
```
After **sync** you will see that **Build Variant** window will have more options in **Active Build Variant**.
>[color=lightblue]
## Set up in build.gradle (app/build.gradle)
1. Open build.gradle(app/build.gradle)
2. Inside Android {} set up the product flavors
3. Sync Gradle
>[color=lightblue]
## Set up in separated .gradle file
1. New > File
2. Name the file with **.gradle extension**
3. Open build.gradle(app/build.gradle)
4. Link build.gradle to the newFile.gradle by using **apply from: 'location'**
5. Go to newFile.gradle
6. Set up product flavor
**Note:** Remember to add **android {}** by yourself
>[color=lightblue]
# Product Flavor Information
Profuct Flavor information can be set up by 3 methods:
1. **buildConfigField:** Values are shown in BuildConfig file.
2. **resValue:** Values are shown in res(generated) > values > gradleResValues.
3. **manifestPlaceholders:** Values can be used in manifest directly.
## **buildConfigField**
This one will generate a file called **BuildConfig**, which will set up all constants set in gradle.
### **How to set up?**
Just put **buildConfigField "type", "FieldName", "FieldValue"**
Note: For String FieldValue a **\ (slash)** must be used.
As we can see below, we can also set up **applicationId, versionCode, versionName** for each of our product flavor.
**Example:**
```java=
flavorDimensions "productFlavor"
def BASE_URL = "BASE_URL"
def APP_NAME = "APP_NAME"
productFlavors {
flavor {
applicationId "com.zc.learngradle0"
versionCode 2
buildConfigField "String", BASE_URL, "\"FieldValue\""
buildConfigField "String", APP_NAME, "\"AppName\""
buildConfigField "int", "FieldInt0", "0"
}
}
```
### **BuildConfig File**
>[color=lightpink]
>**Note:** Sync may not be enough for it to appear, you may need to run the project once.
### **What if your applicationId, versionCode, versionName did not change?**
If you are **using another .gradle file** check the import place in build.gradle.
As shown in the image below, check **build.gradle (app/build.gradle)** whether you have set up **defaultConfig** with the same fields as the one you have wrong in BuildConfig.
If you did, check:
* Whether you have really stated the variables in your variant.
* Close BuildConfig, ReSync and Rebuild to check again
If not, then it may be another issue.
**Note:**
DefaultConfig acts as default state when you did not specify the variables for any variant.
## **resValue**
This one will show its values in **res(generated) > values > gradleResValues**.
### **How to set up?**
```java=
flavorDimensions "productFlavor"
productFlavors {
flavor {
// Will be put in res(generated) > values > gradleResValues
// Note: res > values > strings.xml must not have same string id (Error: Duplicate resources)
resValue "string", "base_url_base", "www.example.com"
}
}
```
### **Output location: gradleResValues**
**res(generated) > values > gradleResValues**
>[color=pink]
## **manifestPlaceholders**
Values generated can be used directly by **manifest by using ${constantName}**.
### **How to set up?**
By setting an **array for manifestPlaceholders** we can set up **key-value** for each constant/variable we want.
**Example:**
```java=
flavorDimensions "productFlavor"
productFlavors {
flavor {
manifestPlaceholders = [
"app_name": "FlavorApp",
"app_icon": "@mipmap/ic_launcher",
"app_round_icon": "@mipmap/ic_launcher_round"
]
}
}
```
### **How to use the values set up in the manifestPlaceholder?**
#### **In Manifest file**
By using **${keyName}** we can call out the value set up in the manifestPlaceholder without any problem.

#### **In Project**
If we want to retrive **manifestPlaceholder' values** in our project too, we have to use **meta-data** in manifest.
>Be aware to put meta-data inside the Application section. [color=red]
>**Note:** the meta-data name cannot use manifestPlaceholder values as name, meaning we cannot use name = ${...}
>
**In Activity Retrive Example:**
```java=
try{
PackageManager packageManager = getApplicationContext().getPackageManager();
ApplicationInfo appInfo = packageManager.getApplicationInfo(this.getPackageName(), PackageManager.GET_META_DATA);
Log.d("manifestPlaceholder", appInfo.metaData.getString("app_icon"));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
```
# Reference
https://medium.com/stepstone-tech/how-to-build-17-apps-with-a-single-android-project-and-not-go-crazy-91d025adf0f0