How can be defined that debuggable=true is enabled in releaseBuildConfig, but just for a specific set of flavors:
This is the example code, including the trial (which does not work):
flavorDimensions "project", "environment"
productFlavors {
basic {
dimension "project"
}
advanced {
dimension "project"
}
flavorDevelopment {
dimension "environment"
applicationId "ch.myproject.app.development"
debuggable true // this does not work
}
flavorTest {
dimension "environment"
applicationId "ch.myproject.app.test"
debuggable true // this does not work
}
flavorIntegration {
dimension "environment"
applicationId "ch.myproject.app.integration"
debuggable true // this does not work
}
flavorProduction {
dimension "environment"
applicationId "ch.myproject.app.production"
// just here debuggble has to be on the default (in buildTypes.debug = on AND in buildTypes.release = off )
// this is working
}
the "debuggable true" statements wont work in the code example above.
But it should give you an impression, what I try to make.
The only productive Release I' gona make is the flavorProduction.
There I'm using the default behavior which is working fine.
But all the other internal releases flavorDevelopment, flavorTest, flavor Integration, those I would like to have with enabled debugging capability.
I tried a second approach:
applicationVariants.all { variant ->
// setting all releases expecting the Production one to debuggable
if (!variant.buildType.name.contains("ProductionRelease")) {
variant.buildType.debuggable = true
}
}
But there I'm getting the message:
Error:(132, 0) Cannot set readonly property: debuggable for class: com.android.build.gradle.internal.api.ReadOnlyBuildType
Does anybody know how to configure this with gradle?
thanks in advance luke
debuggable is a property of the BuildType object, and not of the ProductFlavor object, and so (as you have found), writing debuggable true inside a product flavor will have no effect.
Generally you will have a debug build type and a release build type, and then you will have build variants like flavorProductionDebug and flavorProductionRelease. It sounds like that's not enough for you, and you need to have whatever is different between your debug and release build types be maintained while also having debuggable true.
To achieve this, you can make a third build type.
buildTypes {
debug { ... }
release { ... }
releaseDebuggable {
initWith release
debuggable true
}
}
Now your releaseDebuggable build type will be exactly like your release build type, but debuggable!
This has the side-effect of creating a fooReleaseDebuggable build variant for all of your product flavors. If you want to suppress all those except for flavorProductionReleaseDebuggable, you could use the variantFilter interface.
There is a way to achieve this, just set debuggable attribute to be true in manifest in every source set of expected product flavors.
Step 1: Create source set of product flavors.
New source set in app/src/[flavor-name] and create a AndroidManifest.xml in it. Just like the following:
Step 2: Define debuggable in manifests
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:debuggable="false"
tools:ignore="HardCodedDebugMode" />
</manifest>
tools:ignore="HardcodedDebugMode" is used to suppress warnings.
That's it, you're good to go. No need to touch your build.gradle files.
There's always a way.
def getCurrentFlavor() {
String tskReqStr = getGradle().getStartParameter()
.getTaskRequests().toString()
Pattern pattern
if( tskReqStr.contains("assemble"))
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else if(tskReqStr.contains("bundle"))
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if(matcher.find())
return matcher.group(1).toLowerCase()
else return ""
}
android {
buildTypes {
release {
debuggable = getCurrentFlavor()
.containsIgnoreCase(("production")
}
debug {
debuggable = getCurrentFlavor()
.containsIgnoreCase(("production")
}
}
flavorDimensions "enviroment"
productFlavors {
flavorTest { ... }
flavorDevelopment { ... }
flavorIntegration { ... }
flavorProduction { ... }
}
}
Related
How to set variable depending on current buildType, I have tried this
String url = "https://dev.myurl.com"
tasks.whenTaskAdded { task ->
if (task.name == 'generateReleaseBuildConfig' || task.name == 'generateDebugBuildConfig') {
if (task.name == 'generateReleaseBuildConfig') {
url = "https://prod.myurl.com"
}
}
}
But no matter if the current buildType is Release or Debug, the tasks generateReleaseBuildConfig and generateDebugBuildConfig are both executed, so I never get the value depending on the current buildType. I specify that this variable is used later in build script and not in Java code.
I have tried several solutions found in SO but none worked for me
This example is from my own application. It's working fine
Put follow code on your app\build.gradle
buildTypes {
debug {
...
buildConfigField "String", "SERVER_URL", '"http://..."'
}
release {
...
buildConfigField "String", "SERVER_URL", '"http://..."'
}
}
IMPORTANT: sync your gradle
And then put follow call on your class
String URL = BuildConfig.SERVER_URL
You can use buildConfigField. It looks like this:
buildConfigField('String', 'API_URL', "\"URL\"")
Place it in gradle, under different buildType. And to get it use this:
BuildConfig.API_URL
That will return this value depends of buildType
UPDATE
Are sure you placed it correctly?
buildTypes {
debug {
//...
buildConfigField('String', 'API_TEST', "\"URL\"")
}
release {
//...
buildConfigField('String', 'API_TEST', "\"URL\"")
}
}
Is there a way to group gradle properties to be reused? I can accomplish the following by having duplicate properties but I am trying to avoid this by grouping them in a common place. I have the following build types
buildTypes {
debug {}
qa {
applicationIdSuffix = ".qa" //Duplicate
}
qa2 {
applicationIdSuffix = ".qa" //Duplicate
}
release {}
}
flavors {
flagship {}
other1 {}
other2 {}
}
I already have different flavors defined so I don't think I can place the common properties in different flavors. I was hoping I'd be able to do something like
def commonQaProps {
applicationIdSuffix = ".qa"
//Other properties
}
and then have
qa { commonQaProps }
qa2 { commonQaProps }
Is something like this possible?
After reading the documentation if you're building one buildType off of another you can use initWith.
buildTypes {
debug {}
qa {
applicationIdSuffix = ".qa" //Duplicate
}
qa2 {
initWith qa
//Customize other properties here
}
release {}
}
I still would like to know if grouping properties is possible to use in many variants that don't inherit from each other.
I have an android app that I want customized for different clients, usually changed colors.
I could use flavors, but
The problem is that every app should have 2 stages (so, 2 apps for every client), 1 for QA and 1 for Prod and they use different rest-api urls, custom for each client.
What would be ideal for me is a way to nest flavors so I can define properties for each,but it's not supported. This will also allow me to modify some layouts for client_1 and use the rest from main, which I also need to do. Example:
productFlavors {
client_1 {
dev {
buildConfigField "String", "API_URL", "https://...."
}
prod {
buildConfigField "String", "API_URL", "https://...."
}
}
client_2 {
dev { //...
}
prod {
//...
}
}
}
Any idea how I can achieve that?
The other option would be to have a common library app and have different apps for different clients with their config, but that would make it more complex.
In my project i used , build types with product flavours. I will explain it here.
My project looks like this,
and add this lines in the gradle file,
buildTypes {
prod {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
dev {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
client_1 {
applicationId "com.example.client_1"
versionCode 1
}
client_2 {
applicationId "com.example.client_2"
versionCode 1
}
}
When the app is based on more than one criteria, instead of creating a lot of flavors you can define flavor dimensions.
The flavor dimensions define the cartesian product that will be used to produce variants.
Example:
flavorDimensions("dimA", "dimB")
productFlavors {
row1 {
...
dimension = "dimA"
}
row2 {
...
dimension = "dimA"
}
row3 {
...
dimension = "dimA"
}
col1 {
...
dimension = "dimB"
}
col2 {
...
dimension = "dimB"
}
col3 {
...
dimension = "dimB"
}
}
This config will produce 18 (3*3*2) variants (if you have the 2 standard build types : debug and release).
The following build variants will be created:
row1-col1-debug
row1-col2-debug
row1-col3-debug
row1-col1-release
row1-col2-release
row1-col3-release
row2-col1-debug
row2-col2-debug
row2-col3-debug
row2-col1-release
row2-col2-release
row2-col3-release
row3-col1-debug
row3-col2-debug
row3-col3-debug
row3-col1-release
row3-col2-release
row3-col3-release
I have created custom buildTypes as follows:
buildTypes {
releasefree.initWith(buildTypes.release)
releasefree {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
releasepro.initWith(buildTypes.release)
releasepro {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationIdSuffix ".pro"
}
debugfree.initWith(buildTypes.debug)
debugfree {
shrinkResources true
applicationIdSuffix ".debug"
debuggable true
}
debugpro.initWith(buildTypes.debug)
debugpro {
shrinkResources true
applicationIdSuffix ".pro.debug"
debuggable true
}
}
I am not going to use the default debug and release build types ever and want to remove them from the build variants list. I have more than a few flavors and the list of variants is too huge. Removing the variants with default debug and release types will help as I'm never going to use them.
I tried using variant filter as follows but it did not work
android.variantFilter { variant ->
if(variant.buildType.name.endsWith('Release') || variant.buildType.name.endsWith('Debug')) {
variant.setIgnore(true);
}
}
Is there something wrong in the way I'm filtering the variants or is it just not possible to remove the variants with default debug and release build types.
Figured it out. It was a really silly mistake on my part.
The above variant filter does work. The names are all lower case and the upper case in the strings i was comparing with were the culprit.
Changing to the following (making compare strings lower case) made it work as expected:
android.variantFilter { variant ->
if(variant.buildType.name.endsWith('release') || variant.buildType.name.endsWith('debug')) {
variant.setIgnore(true);
}
}
or this
android.variantFilter { variant ->
if(variant.buildType.name.equals('release') || variant.buildType.name.equals('debug')) {
variant.setIgnore(true);
}
}
With New Variant APIs, it becomes:
androidComponents {
beforeVariants(selector().withBuildType("release")) { variantBuilder ->
variantBuilder.enabled = false
}
}
ref doc
If u want exclude by name use something like this
android.variantFilter { variant ->
if(variant.name.equals("qaRelease")|| variant.name.equals('something')) {
variant.setIgnore(true);
}
}
If you want to ignore specific build variant , Here is details for understanding.
flavorDimensions "client", "server"
productFlavors {
client1 {
manifestPlaceholders variant : 'Client 1'
dimension "client"
applicationId "com.edupointbd.bb"
}
client2 {
manifestPlaceholders variant : 'Client 2'
dimension "client"
applicationId "com.edupointbd.bb"
}
dev {
dimension "server"
}
staging {
dimension "server"
}
production {
dimension "server"
}
}
variantFilter { variant ->
def names = variant.flavors*.name
// To check for a certain build type, use variant.buildType.name == "<buildType>"
if (names.contains("client1") && names.contains("production")) {
// Gradle ignores any variants that satisfy the conditions above.
setIgnore(true)
}
}
I have a build configuration with 2 build types (debug/release) and 2 flavorGroups (locale/environment).
These are 3 different axes, and I want to determine the packageName of the build variant by all of them.
However, it seems I can only set the full packageName for a given flavor, and then have a packageNameSuffix for the build type - attempting to do a packageNameSuffix for a flavour leads to an Could not find method packageNameSuffix() for arguments [...] error.
Any way around that, so that I could get a package name for each of the resulting build variants, along the lines of: com.app.LOCALE.ENVIRONMENT.TYPE, without having to "unroll" one of the axes into build types (which would lead to duplication)?
Thanks in advance.
You could use the solution I've written about here: https://stackoverflow.com/a/26585241/4177090
In short, you can find out the combined variant using variantFilter and then update the configuration (e.g. the appliciationId) from there:
android.variantFilter { variant ->
def flavorString = ""
def flavors = variant.getFlavors()
for (int i = 0; i < flavors.size(); i++) {
flavorString += flavors[i].name;
}
if(flavorString.equalsIgnoreCase("fooBar")) {
variant.getDefaultConfig().applicationId "com.example.foobar"
}
}
You could use a combination of packageName and packageNameSuffix from productFlavors and buildTypes like the following:
android {
productFlavors {
foo {
packageName "com.example.foo"
versionName "Foo"
}
bar {
packageName "com.example.bar"
versionName "Bar"
}
}
buildTypes {
debug {
packageNameSuffix ".debug"
versionNameSuffix "-debug"
}
release {
packageNameSuffix ".release"
versionNameSuffix "-release"
}
}
}
But if you're using something like flavorGroups, then this may not work for you.
You can also check out this code sample config which adds new buildTypes https://github.com/bradmcmanus/Gradle-Build-Example/blob/master/GradleBuildExample/build.gradle