Android Gradle Group Common Properties - android

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.

Related

How can I detect if a gradle project is of an Application or Library?

I'm writing am Android Studio Gradle plugin and one of the things I need to do is iterate over the projects and detect if they are of type Android Application or library (or a non android project like general java libs).
I tried to use the following code but it doesn't work properly (detects the application but not libraries):
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.LibraryPlugin
...
public void getVariants(){
...
def hasApp = p.plugins.withType(AppPlugin)
def hasLib = p.plugins.withType(LibraryPlugin)
...
}
Are there any other proper ways in Groovy script to detect of a project is of type library ?
project.afterEvaluate {
plugins.withId('com.android.application') {
println("==> module application")
}
plugins.withId('com.android.library') {
println("==> module library")
}
plugins.withId('java') {
println("==> module pure java")
}
}
I have a flavor.gradle defined which is getting imported into application & library modules. I need to add applicationSuffixId only for application flavor. So I done it like this.
def isApplication = plugins.hasPlugin("com.android.application")
android {
flavorDimensions "version"
productFlavors {
dev {
dimension "version"
if (isApplication) {
applicationIdSuffix ".dev"
}
}
qa {
dimension "version"
if (isApplication) {
applicationIdSuffix ".qa"
}
}
beta {
dimension "version"
if (isApplication) {
applicationIdSuffix ".beta"
}
}
prod {
dimension "version"
}
}
}

Setting debuggable true for specific flavor Releases

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 { ... }
}
}

Mobile app clones from same codebase

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

How to initialize a BuildType with the configuration of an existing BuildType?

I want to configure a third BuildType in my project that inherits all the configurations from another BuildType.
How can I do this?
Just use the initWith property with in the build type:
uitesting {
initWith debug
}
You can find more information on the respectively developer page: https://developer.android.com/studio/build/build-variants#build-types
As an alternative you can also use:
<<new_build_type>>.initWith(buildTypes.<<old_build_type>>)
In a real case this looks like:
uitesting.initWith(buildTypes.debug)
uitesting {
...
}
Use jnidebug.initWith(buildTypes.debug) to inherit properties of another build type
Please try something like this
android {
buildTypes {
debug {
applicationIdSuffix ".debug"
}
jnidebug.initWith(buildTypes.debug)
jnidebug {
packageNameSuffix ".jnidebug"
jniDebuggable true
}
}
}
This might be helpful http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types
use .initWith()
mock.initWith(buildTypes.debug)
http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types
In the newer developer guide (https://developer.android.com/studio/build/build-variants), you can use:
android {
buildTypes {
debug {
applicationIdSuffix ".debug"
}
jnidebug {
initWith debug
packageNameSuffix ".jnidebug"
jniDebuggable true
}
}
}

Letting multiple flavorGroups influence packageName in Android gradle build

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

Categories

Resources