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
Related
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.
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 { ... }
}
}
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)
}
}
We have 2 productFlavors (testServer, liveServer) and 2 build types (debug, release).
Due to existing API keys, I have to append package names based on buildType + productFlavor.
For example something like:
buildTypes {
debug {
applicationIdSuffix '.dbg' + (testServer ? '.test' : '.live')
}
release {
applicationidSuffix '' + (testServer ? '.test')
}
}
is this possible? how?
productFlavors {
testServer {
applicationId = "com.example.my.pkg.test"
}
liveServer {
applicationId = "com.example.my.pkg.live"
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
For more information, take a look at the Android documentation regarding application ids.
I have a Gradle Android Project with this product Groups and Flavors configuration:
/*
* Define different flavor groups
*/
flavorGroups 'market', 'version'
/*
* Defile product flavors
*/
productFlavors {
amazon {
flavorGroup 'market'
}
google {
flavorGroup 'market'
}
flav1 {
flavorGroup 'version'
packageName 'com.company.flav1'
}
flav2 {
flavorGroup 'version'
packageName 'com.company.flav2'
}
flav3 {
flavorGroup 'version'
packageName 'com.company.flav3'
}
}
// .. Other stuff
It works great. All sources and resources are merged correctly.
But for specific reasons I need the package suffix to be .amz for the amazon product flavor. How can I achieve that?
I tried this way:
amazon {
flavorGroup 'market'
packageNameSuffix '.amz'
}
but gradle throws an exception.
This is not possible at the moment.
packageNameSuffix is strictly a property of Build Type.
I'd like to offer a way to customize the ProductFlavor's values for a given variant (ie a given combination of all flavor dimensions and of build type) but it's not possible at the moment.
Instead of a new dimension of flavor, you could do a "amzRelease" buildtype that extends the existing release buildtype and add a suffix.
If your current "amazon" flavor does more (configure versionCode/Name/etc...), it won't work though. You could then use both your amazon flavor and a amzRelease build type. It'll create a lot more variants than you need but it'd work until we have some better.
You could use a variant of the solution I've written about here: https://stackoverflow.com/a/26585241/4177090
In short, you can find the combined variants using variantFilter and then update 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.contains("amazon")) {
variant.getDefaultConfig().applicationId variant.getDefaultConfig().applicationId + ".amz"
}
}
Working solution for gradle 1.0.0+:
android.applicationVariants.all { variant ->
def flavorName = variant.getVariantData().getVariantConfiguration().getFlavorName()
def mergedFlavour = variant.getVariantData().getVariantConfiguration().getMergedFlavor();
if (flavorName.toLowerCase().contains("amazon")) {
mergedFlavour.setApplicationId(mergedFlavour.getApplicationId() + ".amz")
}
}