To install two different instances of the same app is easy. I just use productFlavors.
The problem comes when I install the app from Google Play and try to install another flavor. I can't have an app from Google Play and a flavor one at the same time but two flavors apps yes.
How can I install both apps in the same phone, Google Play app and Flavor app.
PD: I am using different flavors, this is an example of them:
QA {
resValue "string", "app_name", "My app QA"
applicationId "com.myapp.qa"
}
GOOGLEPLAY{
resValue "string", "app_name", "My app GOOGLE PLAY"
applicationId "com.myapp.release"
}
TESTING {
resValue "string", "app_name", "My app TEST"
applicationId "com.myapp.test"
}
DEVELOPMENT {
resValue "string", "app_name", "My app DEV"
applicationId "com.myapp.dev"
}
Define Flavors
android {
defaultConfig {
applicationId "com.example.myapp"
}
productFlavors {
free {
applicationIdSuffix ".free"
}
pro {
applicationIdSuffix ".pro"
}
}
}
The key is the applicactionIdSuffix
android {
...
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
}
Related
I am trying to add a second flavor dimension to an existing Android project. I already had a dimension for different environments (DEV, BETA, PROD), each with their own backend API and their own application id (to be able to install apps connected to several environments on the same device). And now I want to add another dimension for 2 variants of my app, a general one with all the features, and a specific one with a subset of features. And in addition to that, I still have the default debug and release build types I want to keep.
So here is what my configuration in build.gradle looks like so far:
android {
compileSdkVersion 30
defaultConfig {
applicationId "com.example"
minSdkVersion 21
targetSdkVersion 30
versionCode 56
versionName "1.1.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [
appAuthRedirectScheme: 'com.example'
]
}
signingConfigs {...}
buildTypes {
debug {...}
release {...}
}
flavorDimensions "env", "variant"
productFlavors {
dev {
dimension "env"
applicationIdSuffix ".dev"
resValue 'string', 'backend_url', 'https://dev.example.com/api/v1/'
manifestPlaceholders = [
appAuthRedirectScheme: 'com.example.dev'
]
}
beta {
dimension "env"
applicationIdSuffix ".beta"
resValue 'string', 'backend_url', 'https://beta.example.com/api/v1/'
manifestPlaceholders = [
appAuthRedirectScheme: 'com.example.beta'
]
}
prod {
dimension "env"
resValue 'string', 'backend_url', 'https://example.com/api/v1/'
manifestPlaceholders = [
appAuthRedirectScheme: 'com.example'
]
}
general {
dimension "variant"
applicationId "com.example"
}
specific {
dimension "variant"
applicationId "com.example.specific"
}
}
...
}
As you can see, I will be able to have an application variant specific to each environment/variant flavor by combining applicationId and applicationIdSuffix.
But I also need to have the corresponding mapping in manifestPlaceholders, knowing that the appAuthRedirectScheme placeholder is not integrated inside of my project's manifest, but in the openId Appauth dependency, so I can't just have several manifests in the various flavor directories like I have read elsewhere.
Is there a way to define a build setting in build.gradle that is specific to each flavor dimension combination? In other words, I would like to have different values of manifestPlaceholders for devGeneral, devSpecific, betaGeneral, betaSpecific, prodGeneral and prodSpecific.
I don't specially advice this solution, but you could try the following approach:
applicationVariants.all { variant ->
if(variant.productFlavors.get(0).name == "dev") {
if (variant.buildType.name == "debug" ) {
variant.getMergedFlavor().manifestPlaceholders = [
appAuthRedirectScheme: 'com.example.dev'
]
}
if (variant.buildType.name == "release" ) {
variant.getMergedFlavor().manifestPlaceholders = [
appAuthRedirectScheme: 'com.example.dev.foo'
]
}
}
if(variant.productFlavors.get(0).name == "beta") { ... }
if(variant.productFlavors.get(0).name == "prod") { ... }
}
So I've been working on a bit of a white label style project for a while, and I've run into a bit of an issue with extensibility. Specifically, the way the project works, I need to be able to support multiple backend environments, each with unique credentials, on a per-client basis.
I've baked this behavior into the gradle using two flavor dimensions, one for the client and one for the backend, but I'm having a bit of trouble in getting them to gel together as seamlessly as I'd like.
Here's an example of the gradle setup:
productFlavors {
client1 {
applicationId "com.app.client1"
dimension "customer"
resValue "string", "app_name", "Client 1"
}
client2{
applicationId "com.app.client2"
dimension "customer"
resValue "string", "app_name", "Client 2"
}
dev {
ext {
packageExtension = ".DEV"
}
dimension "environment"
resValue "string", "url", "https://dev.hostname.com/"
}
uat {
ext {
packageExtension = ".UAT"
}
dimension "environment"
resValue "string", "url", "https://uat.hostname.com/"
}
stage {
ext {
packageExtension = ".STAGE"
}
dimension "environment"
resValue "string", "url", "https://stg.hostname.com/"
}
prod {
ext {
packageExtension = ""
}
dimension "environment"
resValue "string", "url", "https://hostname.com/"
}
}
This works great for granting access to the right environment and unique code for each client, but it means that I can't include the client ID in the gradle. I have to stick it in a resource file out in the client1Dev directory and the like in order to get the right value at run time.
My question is, is there a way to move the client ID into gradle and get the right value based on the combination of customer and environment flavors?
For example, what I would like to do is something like:
client1 {
applicationId "com.app.client1"
dimension "customer"
resValue "string", "app_name", "Client 1"
dev{
resValue "string", "clientId", "1032145d8eefa00aff0098b08c9d"
}
uat{
resValue "string", "clientId", "8654684561584798531985964/56"
}
}
client2{
applicationId "com.app.client2"
dimension "customer"
resValue "string", "app_name", "Client 2"
dev{
resValue "string", "clientId", "89612ad8967a00aff0098b08c08e"
}
uat{
resValue "string", "clientId", "8612ad890981237409d0ab08c08f"
}
}
Something along these lines that would allow me to store my client ID in the gradle file along with the other backend setup info. I can't find anything about this kind of thing though, and I'm hoping someone on here can shed some light on how to do it, or at least tell me it's impossible.
Thanks!
You could always use separate source trees for the multi-flavor combination and store the Strings directly in the correct resource (since that's essentially what resValue "string" "{ID}" "{VALUE}" is doing anyway).
src/
main/
java/
res/
values/
strings_ids.xml
<string name="clientId">override_me</string>
client1Dev/
client1Uat/
client2Dev/
res/
values/
strings_ids.xml
<string name="clientId">89612ad8967a00aff0098b08c08e</string>
client2Uat/
res/
values/
strings_ids.xml
<string name="clientId">8612ad890981237409d0ab08c08f</string>
Or, if you really want to keep in inside the build.gradle file, you could script it with something (less elegant) along the lines of:
android.applicationVariants.all { variant ->
if (variant.getFlavorName().equalsIgnoreCase("client1Dev")) {
variant.resValue "string", "clientId", "1032145d8eefa00aff0098b08c9d"
}
else if (variant.getFlavorName().equalsIgnoreCase("client1Uat")) {
variant.resValue "string", "clientId", "8654684561584798531985964/56"
}
}
But you can see the latter will get nasty, pretty quickly
I built an app and registered it with Firebase as part of a project that includes three other apps. Here's what my buildTypes in the app gradle build file looks like:
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "int", "RULE_DEBUG_LEVEL", "0"
}
releaseDebuggable {
debuggable true
buildConfigField "int", "RULE_DEBUG_LEVEL", "1"
}
debug {
//applicationIdSuffix '.debug'
versionNameSuffix " Debug"
buildConfigField "int", "RULE_DEBUG_LEVEL", "1"
}
and the productFlavors are as follows:
flavorDimensions "fmplus"
productFlavors {
String name = "fmplus"
fmplus {
name = "fmplus"
applicationId getPackageName(name)
resValue 'string', 'app_name', getAppName(name)
resValue 'color', 'accent', getThemeColor(name)
resValue 'color', 'accentDark', getThemeColorDark(name)
}
fmplus_nab_htc_one_m8 {
name = "fmplus"
applicationId getPackageName(name)
applicationIdSuffix ".nab_htc_one_m8"
versionNameSuffix "-nab_htc_one_m8"
resValue 'string', 'app_name', getAppName(name)
resValue 'color', 'accent', getThemeColor(name)
resValue 'color', 'accentDark', getThemeColorDark(name)
}
fmplus_nyx_supraim_sn10 {
name = "fmplus"
applicationId getPackageName(name)
applicationIdSuffix ".nyx_supraim_sn10"
versionNameSuffix "-nyx-supraim-sn10"
resValue 'string', 'app_name', getAppName(name)
resValue 'color', 'accent', getThemeColor(name)
resValue 'color', 'accentDark', getThemeColorDark(name)
}
changeFileManifest(name)
}
Another programmer on our team handled the flavor labelled 'fmplus_nyx_supraim_sn10' and I'm doing 'fmplus_nab_htc_one_m8'. Both apps appear in Firebase under the same project, but Firebase reports his events but not mine. I've been struggling with this for some time now and have run out of ideas. Does anyone have an idea what I'm doing wrong. And yes, I downloaded and installed the google-services.json file and rebuilt the app before running it, just like the docs say.
The problem was in the app gradle file: Android Studio 3.0 requires a default dimensions statement, which I have, but what I also needed to do was add a dimension statement to the build flavor in question. The other developer, whose app didn't have this problem, was using Studio 2.3.3.
i want to publish a paid app and free app
i have created flavor of free and paid using this code
productFlavors {
free {
applicationId "com.example.myapp.free"
versionName "1.0-free"
// this boolean can be accessed in java classes by using BuildConfig class
// and now you can identify if your app is the paid version or not
buildConfigField "boolean", "PAID_VERSION", "false"
}
paid {
applicationId "com.example.myapp.paid"
versionName "1.0-paid"
buildConfigField "boolean", "PAID_VERSION", "true"
}
}
I want to know how can upload this app
we need two diffretnt apk for that (paid relese apk and free apk)
or single apk
i need both variant available in playstore
If You have two flavor variant
like
Free with package name as
applicationId "com.example.myapp.free"
Paid with package name as
applicationId "com.example.myapp.paid"
Both are different applicationId so you need to upload in two different apps in play store, Because your applicationId is a playstore app id So it must be a unique
or
You have to remove this line in both flavor and use common applicationId
then
handle like this following way
defaultConfig {
applicationId "com.example.myapp"
}
productFlavors {
free {
versionName "1.0-free"
buildConfigField "boolean", "PAID_VERSION", "false"
buildConfigField "String", "BuildType", "Free"
}
paid {
versionName "1.0-paid"
buildConfigField "boolean", "PAID_VERSION", "true"
buildConfigField "String", "BuildType", "Paid"
}
}
Handle in java code
public void manageFeaturesWithBuildType()
{
String buildType = BuildConfig.BuildType;
if(buildType.equals("Paid"))
{
//Here Enable or Disable your features for paid Build
}
else
{
//Here Enable or Disable your features for free Build
}
}
You got this type of Build variant as shown in image: In your case you can see paidDebug and freeDebug option.
If you want to release paid version then you have to select paidDebug and if you want to release free version then you have to select freeDebug.
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.