How is it possible to identify the current flavor being compiled. I'm trying to add a file to compile only if I'm compiling a certain product flavor.
buildTypes {
android.applicationVariants.all { variant ->
variant.productFlavors.each() { flavor ->
if (flavor.name.equals(currentFlavorName)) {
The problem is that I can't seem to find where the currentFlavourName of the flavor which I am currently building is located.
just put the strings you want for flavor1 into:
src/flavor1/res/values/strings.xml
and the strings for flavor2 into:
src/flavor2/res/values/strings.xml
no need to put logic into your gradle file
Android uses a unique build process regarding your resources for different flavors and it is very easy to control.
if you set up your main source:
project-name
------------/app
---------------/src
-------------------/main
------------------------/res
----------------------------/values
------------------------/java
-------------------/development
-------------------------------/res
-----------------------------------/values
-------------------------------/java
-------------------/production
------------------------------/res
----------------------------------/values
------------------------------/java
This would be a bottom up approach from product flavor into main. Meaning if you have a strings.xml with items having the same name existing in development/res/values and have values that also exist in main/res/values/strings.xml these will be over written (and same would go for the production flavor) based on the build variant defined in your gradle file.
android {
productFlavors {
production {
applicationId "com.test.prod"
versionName "1.0.0"
}
development {
applicationId "com.test.dev"
versionName "1.0.0"
}
}
I don't know if exits a method to get the currentFlavor. I haven't found it yet.
A ugly solution can be
variant.productFlavors.each() { flavor ->
if (flavor.name.equals("flavor1")) {
//..........
}
}
However, if you want to be able to control which strings.xml you are using, you can achieve it in different ways.
First of all you can just define a xml file in your flavor folder.
app/src/main/res/values/ -> for common resources
app/src/flavor1/res/values -> resources for flavor1
app/src/flavor2/res/values -> resources for flavor2
This doesn't require any config in your build.gradle script.
A second option is to define a resource value using build.gradle.
Something like:
productFlavors {
flavor1 {
resValue "string", "app_name", "IRCEnterprise"
}
//....
}
Another option is to create some field in your BuildConfig class using this kind of script.
productFlavors {
flavor1 {
buildConfigField "String", "name", "\"MY FLAVOR NAME\""
}
}
Related
I have an application with many flavors (A,B,C) and two build types (debug,release)
In the build type debug I add a suffix to the application ID like so:
debug {
applicationIdSuffix '.debug'
}
This is fine for flavors A and B but I can't append .debug to flavor C's application ID.
I have looked at overriding on the variant like I have for the versionCode but no luck.
applicationVariants.all { variant ->
def changedVersionCode = variant.versionCode
variant.
variant.outputs.each { output ->
if (variant.buildType.name != "debug") {
output.setVersionCodeOverride(project.ext.versionCode)
changedVersionCode = project.ext.versionCode
}
}
changeApkFileName(variant,changedVersionCode)
}
Is it possible to override a variants application ID depending on the flavor. For example my plan was to do something like this:
variant.buildType.name.replace('.debug','')
Is it possible to override a variants application ID depending on the flavor
Yes it is possible.
The reason you are not able to see the expected id is:
Because Gradle applies the build type configuration after the product flavor, the application ID for the "C" build variant will be "<your-applicaion-id>.debug".
So if you want it to be different for different flavors then you have to segregate the applicationIdSuffix for different flaovors and remove it from debug {} as follows:
android {
defaultConfig {
applicationId "<your-application-id>"
}
productFlavors {
A {
applicationIdSuffix ".debug"
}
B {
applicationIdSuffix ".debug"
}
C {
applicationIdSuffix ""
}
}
}
For more details, refer to official documentation.
Gradle supports multiple flavor builds for Android Applications. How can I export an environment variable which has different flavor values? For example, export FLAVOR with value "flavor1" when flavor1 is built and "flavor2" for flavor2 build.
android {
...
productFlavors {
flavor1 {
...
}
flavor2 {
...
}
}
}
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.
I have 2 versions of app: paid-app and free-app. I use gradle and Android Studio.
I have next folder structure:
src folder, and inside it 3 folders: main, paidapp, freeapp - where paidapp and freeapp are flavors.
My configs:
defaultConfig {
applicationId "com.company"
}
buildTypes {
debug {
applicationIdSuffix '.dev'
}
}
productFlavors {
freeapp {
}
paidapp {
applicationId 'com.company.paidapp'
}
}
What I want: have on my phone 4 apps:
package com.company.dev, name "dev freeapp"
package com.company.paidapp.dev, name "dev paidapp"
package com.company, name "freeapp"
package com.company.paidapp, name "paidapp"
package is ok, gradle manage it automatically, but how to create different names for app?
App name located in strings.xml
in src/paidapp/res/values/strings.xml:
<string name="appName">dev paidapp</string>
in src/freeapp/res/values/strings.xml:
<string name="appName">dev freeapp</string>
I looked there - http://tools.android.com/tech-docs/new-build-system/resource-merging
The priority order is the following:
BuildType -> Flavor -> main -> Dependencies.
So I can chose or string from BuildType or from Flavor, but how to combine BuildType and Flavor?
Just create a folder src/freeappRelease/res/values/ and add your very specific strings in this folder.
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){}
Before i build android project to two different application paid and free.
I changed each values and strings so yesterday I made a big mistake.
So, I'm laerning how to use gradle to build my app.
My app have some differents.
app name (just add suffix '-Free') -> values/string.xml
change flag in my *.java
// signingConfigs is ommited.
productFlavors{
free{
packageName "my.app.free"
versionCode 20
signingConfig signingConfigs.freeConfing
copy{
from('/res'){
include '**/*.xml'
}
into 'build/res/'
filter{
String line -> line.replaceAll("android:label=\"#string/app_name\"", "android:label=\"#string/app_name_free\"")
}
}
copy{
from('/src'){
include '**/*.java'
}
into 'build/src/'
filter{
String line -> line.replaceAll("public static final Boolean IS_FULL_VER = true;", "public static final Boolean IS_FULL_VER = false;")
}
}
}
paid{
packageName "my.app.paid"
versionCode 20
signingConfig signingConfigs.paidConfing
}
}
but, built app changed nothing at all.
What i missed?
See the documentation on product flavors:
http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-flavors
In your build.gradle, in each flavor, you can define flags to be generated in your BuildConfig.java file:
productFlavors {
free {
packageName "com.company.appfree"
buildConfig "public final static com.company.common.MonetizationType monetizationType = com.company.common.MonetizationType.FREE;"
}
paid {
packageName "com.company.apppaid"
buildConfig "public final static com.company.common.MonetizationType monetizationType = com.company.common.MonetizationType.PAID;"
}
}
This example uses an enum (that you need to define somewhere in your java code):
public enum MonetizationType {
PAID, FREE
}
You can now use this anywhere like this:
if (BuildConfig.monetizationType == MonetizationType.FREE) { ... }
For overriding resources, you can create different resource files in the source folders for each flavor:
Use the following structure
app/build.gradle
app/ [.. some other files...]
app/src/main/
app/src/main/java
app/src/main/res
app/src/main/assets
app/src/main/AndroidManifest.xml
app/src/free/res/values/apptitle.xml
app/src/paid/res/values/apptitle.xml
apptitle.xml would be a string resource file (just like strings.xml), but with only one string: the one you want to be different depending on the flavor.
(You don't need have a apptitle.xml in your main/res directory).
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_title">App Title (or whatever you want)</string>
</resources>
You might be able to override strings in different ways, but I like to keep the overridden strings separate from the rest for clarity.
The accepted answer is not working with the newer versions of Gradle.
You need to replace buildConfig with buildConfigField to get the same result:
productFlavors {
free {
packageName "com.company.appfree"
buildConfigField "com.company.common.MonetizationType", "MONETIZATION_TYPE", "company.common.MonetizationType.FREE"
}
paid {
packageName "com.company.apppaid"
buildConfigField "com.company.common.MonetizationType", "MONETIZATION_TYPE", "company.common.MonetizationType.PAID"
}
}
treesAreEverywhere's answer (as well as user name) is right on. But it's also very valuable to know that Android Studio will greatly simplify the process of creating build flavor or attribute specific resource files.
In the AS project window, right click on the res/values folder and select New > Values resource file. Then name it (e.g., "strings"), select the Source set if not the default, and select any desired qualifiers (e.g., Screen Width = 800). This is the easiest way to make sure you're putting your resource overrides where the compiler wants them.
This is how I did in my project. I created multiple build types instead of flavours. This solution will add a prefix to your package name based on what build type you are trying to assemble. For ex, for dev the package name will be com.sample.myapp.dev and similarly for beta package name will be changed to com.sample.myapp.release. You can tweak it to get Free and Paid prefixes. Hope it would help.
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.production
applicationIdSuffix '.release'
versionNameSuffix '-RELEASE'
}
dev {
signingConfig signingConfigs.debug
applicationIdSuffix '.dev'
versionNameSuffix '-DEV'
}
beta {
signingConfig signingConfigs.debug
applicationIdSuffix '.beta'
versionNameSuffix '-BETA'
}
debug {
signingConfig signingConfigs.debug
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
debuggable true
}
}