I have a gradle config as setup below. To allow for side by side installs of different builds/flavors
buildTypes {
release {
}
debug {
applicationIdSuffix ".debug"
// Somehow add debug suffix to app ID?
}
}
productFlavors {
ci {
applicationId "com.myapp.ci"
ext.betaDistributionGroupAliases = "mobileworkforce.ci"
resValue "string", "app_name", "AppName.CI"
}
staging {
applicationId "com.myapp.staging"
resValue "string", "app_name", "AppName.Staging"
}
production {
applicationId "com.myapp"
resValue "string", "app_name", "AppName"
}
The issue is that I cannot figure out how to update the app_name string resource to have the suffix "Debug" to the app_name string resource (used as the label for the application)
I was able to create a viable solution using manifestPlaceholders instead of generating string resources. It is not ideal because the result is AppName.Debug.CI instead of AppName.CI.Debug but it works.
buildTypes {
release {
manifestPlaceholders = [ activityLabel:"AppName"]
}
debug {
applicationIdSuffix ".debug"
manifestPlaceholders = [ activityLabel:"AppName.Debug"]
}
}
productFlavors {
def addActivityLabelSuffix = { placeholders, suffix ->
def appName = placeholders.get("activityLabel")
placeholders.put("activityLabel", appName + suffix);
}
ci {
applicationId "com.myapp.ci"
ext.betaDistributionGroupAliases = "mobileworkforce.ci"
addActivityLabelSuffix getManifestPlaceholders(), ".CI"
}
staging {
applicationId "com.myapp.staging"
addActivityLabelSuffix getManifestPlaceholders(), ".Staging"
}
production {
applicationId "com.myapp"
resValue "string", "app_name", "AppName"
}
}
Using getManifestPlaceholders().get("...") I always get null, so I was looking for another solution... and maybe is better because I can get correct order in app name...
// build.gradle
def appNameBase = "My App"
buildTypes {
release {
manifestPlaceholders = [ appNameBase: appNameBase, appNameSuffix: "" ]
}
debug {
manifestPlaceholders = [ appNameBase: appNameBase, appNameSuffix: " Debug" ]
applicationIdSuffix ".debug"
}
}
productFlavors {
one {
manifestPlaceholders = [ appNameFlavor: "One" ]
}
two {
manifestPlaceholders = [ appNameFlavor: "Two" ]
}
}
// AndroidManifest.xml
<application android:label="${appNameBase} ${appNameFlavor}${appNameSuffix}" ...>
In my case I wanted for prod just "My App One" and "My App Two" ad for debug "My App One Debug" and "My App Two Debug" and code above works great.
Related
I need to build an application created with a flavor and create a dynamic variable who points to an applicationId of another flavor (Because the code of an internal library uses the applicationId of other applications) but I don't know how to do that.
Here is the sample code :
defaultConfig {
applicationId "com.sample.mycompany"
}
buildTypes {
release {
}
qualif {
applicationIdSuffix = ".qual"
}
debug {
applicationIdSuffix = ".dev"
}
}
flavorDimensions "client", "nature"
productFlavors {
ClientA {
dimension "client"
applicationIdSuffix = ".A"
}
ClientB {
dimension "client"
applicationIdSuffix = ".B"
}
NatureX {
dimension "nature"
applicationIdSuffix = ".X"
}
NatureY {
dimension "nature"
applicationIdSuffix = ".Y"
// A buildconfigField variable here to get com.sample.mycompany[client].X[buildTypes]
}
NatureZ {
dimension "nature"
applicationIdSuffix = ".Z"
// A buildConfigField variable here to get com.sample.mycompany[client].X[buildTypes]
}
}
When I compile with the Build Variant : ClientANatureYDebug
, final applicationId is com.sample.mycompany.A.Y.dev
I want a dynamic variable with buildConfigField (or something else to retrieve the new variable in Java) who is com.sample.mycompany.A.X.dev
I think to get the final applicationId and replace the applicationIdSuffix of the current nature compilation dimension by .X and get the result in a new variable but I do not know how. Can you help me ?
Fixed with :
buildConfigField "String", "VAL_SHARE_TO_RECEIVER_APP_ID", "APPLICATION_ID.replace(\".Y\", \".X\")"
I'm struggling to find a way for build several apk at once with gradle.
I'd like to have a custom gradle task which considers only variants with enviroment = "production" and all the brands but nonPublishedBrand and buildtype = "release" (see code below).
For each of those variants i need to:
generate the signed apk
upload prodguard mappings to bugsnag with the relative task uploadBugsnag${variant.name}-releaseMapping
rename apk into <brand>-<version>.apk and move it to a common folder $buildDir/myApks
I only found a way to make assemble tasks also run my custom tasks but that's not ideal because i don't want to upload mappings every time a production release variant is built, but only when it's meant i.e. launching a specific gradle task.
Is it possible to achieve that with gradle? Can you please point me in the right direction?
See my build.gradle android section for reference:
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 15
targetSdkVersion 27
versionCode 1000000
versionName "1.0.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
signingConfigs {
release {
storeFile file("keystore/keystore")
storePassword '*******'
keyAlias '*******'
keyPassword '*******'
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
versionNameSuffix ".debug"
manifestPlaceholders = [buildTypePrefix: "D_"]
}
release {
debuggable false
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
manifestPlaceholders = [buildTypePrefix: ""]
}
}
flavorDimensions "environment", "brand"
productFlavors {
//ENVIRONMENTS
staging {
dimension "environment"
applicationIdSuffix ".staging"
versionNameSuffix ".staging"
buildConfigField("String", "BASE_URL", "\"http://baseurl-staging.com\"")
manifestPlaceholders = [environmentPrefix: "S_"]
}
production {
dimension "environment"
buildConfigField("String", "BASE_URL"l, "\"http://baseurl-prod.com\"")
manifestPlaceholders = [environmentPrefix: ""]
}
//BRANDS
nonPublishedBrand {
dimension "brand"
applicationId "${packageBaseName}.nonpublishedbrand"
manifestPlaceholders = [appName: "Non published brand"]
ext {
facebook_app_id = [
staging: "0000000",
prod : "11111111"
]
}
}
brand1 {
dimension "brand"
applicationId "${packageBaseName}.brand1"
manifestPlaceholders = [appName: "Brand 1"]
ext {
facebook_app_id = [
staging: "22222222",
prod : "33333333"
]
}
}
brand2 {
dimension "brand"
applicationId "${packageBaseName}.brand2"
manifestPlaceholders = [appName: "Brand 2"]
ext {
facebook_app_id = [
staging: "44444444",
prod : "555555555"
]
}
}
}
productFlavors {
applicationVariants.all { variant ->
def isDebug = false
if (variant.buildType.name == "debug") {
isDebug = true
}
def isStaging = false
def flavors = variant.productFlavors
def environment = flavors[0]
if (environment.name == "staging") {
isStaging = true
}
def facebookAppId = ""
if (isStaging){
facebookAppId = flavors[1].facebook_app_id.staging
}else{
facebookAppId = flavors[1].facebook_app_id.prod
}
variant.buildConfigField "String", "FACEBOOK_APP_ID", "\"${facebookAppId}\""
}
}
dataBinding {
enabled = true
}
bugsnag {
autoUpload false
}
}
circle.ci is an efficient way to generate builds with each commit. Documentation : https://circleci.com/docs/2.0/
Your circle.yml file would have something like this :
override:
- ./gradlew clean :mobile:assemblePre -PdisablePreDex -Pandroid.threadPoolSize=1 -Dorg.gradle.parallel=false -Dorg.gradle.jvmargs="-Xms2048m -Xmx4608m"
- cp -r ~ build/outputs/apk/build/pre/*.apk $CIRCLE_ARTIFACTS
- ./gradlew clean :mobile:assembleRelease -PdisablePreDex -Pandroid.threadPoolSize=1 -Dorg.gradle.parallel=false -Dorg.gradle.jvmargs="-Xms2048m -Xmx4608m"
- cp -r ~build/outputs/apk/build/release/*.apk $CIRCLE_ARTIFACTS
assemblePre and assembleRelease are tasks executed in above case. You can try to write custom tasks here.
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
Below is an extract from my gradle source code. What I want to achieve is to add suffix to app name when buildType.debug is executed. I tried the following code, but variables are in gradle assigned in sequence as they are written in file and not as task order. So in the example below buildVariant variable will always be equal to Release.
{
def buildVariant = ""
buildTypes {
debug {
manifestPlaceholders = [showDebug: 'true']
buildVariant = " (DEBUG)"
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
manifestPlaceholders = [showDebug: 'false']
signingConfig signingConfigs.myConf
buildVariant = " Release"
}
}
productFlavors {
flavour1{
resValue 'string', 'app_name', 'Flavour1'+buildVariant
}
flavour2{
resValue 'string', 'app_name', 'Flavour2'+buildVariant
}
flavour3{
resValue 'string', 'app_name', 'Flavour3'+buildVariant
}
}
It was a really interesting puzzle to solve, so thanks for the question!
Here what you can do:
android {
compileSdkVersion 23
buildToolsVersion "23.0.0"
defaultConfig {
....
}
buildTypes {
debug {
}
release {
}
}
productFlavors {
FlavorA {
}
FlavorB {
}
}
applicationVariants.all { variant ->
variant.resValue "string", "app_name", '"' + variant.productFlavors.get(0).name + '_' + variant.buildType.name + '"'
}
}
dependencies {
}
As a result, it'd print the app name "FlavorA_debug", "FlavorB_release", etc.
(NB! I ran it with gradle classpath 'com.android.tools.build:gradle:1.3.0' - works great, though I didn't try with older versions)
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.