Android build.gradle importing flavors from another file - android

I have put the product Flavors into another file called other.gradle and it looks like this:
project.ext.myflavors = {
mock {
applicationId "com.mysite.mock"
}
}
and i am able to successfully access the closure in my build.gradle file like this:
myflavors()
but i get an error that mock method is not defined.
Error:Gradle DSL method not found: 'mock()'
Is there no way to just define code from another file and import the code itself into the build file ? Or how can i import the flavors from another file ?

The build flavors could be defined in a separate file (build_flavors.gradle) like this:
android {
productFlavors {
flavorA {
// ...
}
flavorB {
// ...
}
}
}
and then imported into build.gradle:
apply plugin: 'com.android.application'
apply from: './build_flavors.gradle'
android {
// the rest of your android configuration
}

It is perfectly fine to access productFlavors multiple times. So adding some or all flavors in a script included by your build script will work.
Create a Gradle script that contains the logic that decides which flavor(s) should be added:
if (someCondition()) {
android {
productFlavors {
one {
applicationId = 'com.example.oneapp'
}
}
}
} else {
android {
productFlavors {
two {
applicationId = 'com.example.twoapp'
}
}
}
}
Now include this script from your build script. Reusing the scripts is easy if you put it under (a subfolder of) the root project. For example:
apply from: rootProject.file('build-scripts/flavor-picker.gradle')
Note that your IDE may not notice changes to the flavor selection script or gradle.properties, so if you make changes to them you will probably have to manually reimport the Gradle files to see the correct set of available tasks.

Related

Best way to apply a gradle plugin only to a specific build variant

What is the best way to apply a gradle plugin to only a specific build variant. For example we might have
usStage
usDebug
usProduction
but a plugin has a lot of build overhead for developers (several minutes), and has no need to run on usStage and usProduction. Normally for libraries you would just use something like releaseImplementation, but I am not aware of anything like this existing at the gradle plugin level.
So right now we have somethig like this at the top of our app/build.gradle.kts in Android
plugins {
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("com.heapanalytics.android")
id("com.gladed.androidgitversion") version "0.4.14"
id("jacoco-reports")
}
where id("com.heapanalytics.android") is the culprit of slow build times on debug, where it is not even needed.
Is there a way that within our build variants, to only apply this for usProduction?
I have tried something like this:
plugins {
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("com.gladed.androidgitversion") version "0.4.14"
id("jacoco-reports")
}
android {
defaultConfig {
...
signingConfigs {
create(release) {
...
}
getByName(debug) {
...
}
}
buildTypes {
getByName(debug) {
...
}
getByName(release) {
...
apply(plugin = "com.heapanalytics.android")
...
}
But it just applies the plugin to every variant still, I believe because that block configures all variants even when you are only building one.
if (project.hasProperty(BuildProperties.Metrics.ENABLE_HEAP)) {
apply(plugin = "com.heapanalytics.android")
}
Tried something like this too, which may work, but was not really sure it is the best way. Feels hacky.
You can do this in many ways but for the most recent solution I know and use do:
android {
productFlavors {
flavourName{
apply plugin: 'com...'
}
}
}
For more solutions please reference to here.

Android Huawei maps agconnect-services.json can't be located

I have the issue with Huawei maps after introducing product flavours and issue is referenced to the fact that agconnect-services.json can't be located
E/HMSSDK_AGCUtils: Get client/cp_id failed: java.io.FileNotFoundException: agconnect-services.json
So everything was working fine until product flavours are introduced.
The configuration of product flavours are following:
flavorDimensions "provider"
productFlavors {
huawei {
dimension "provider"
}
google {
dimension "provider"
}
}
sourceSets {
huawei {
java {
srcDirs 'src/huawei/java'
}
res {
srcDirs 'src/huawei/res'
}
}
google {
java {
srcDirs 'src/google/java'
}
res {
srcDirs 'src/google/res'
}
}
}
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Huawei"))
{
apply plugin: 'com.huawei.agconnect'
}
classpath 'com.huawei.agconnect:agcp:1.6.3.300'
So the package name keeps the same nothing is changing for flavour. I tried positioning .json file to app/src/huawei but nothing helped.
This is my current setup.
I tried positioning .json file to app/src/huawei, app/src/debugHuawei, app/src/debugHuawei, app/, app/src/huaweiDebug, app/src/debug/huawei but didn't help.
Thanks in advance
You could try configuring the directory according to the current options of Build Variant. like following:
you have to put this agconnect-services file outside the src folder:
just app/agconnect-services.json
also in your screenshot there are 2 agconnect-services.json files, delete them and put only 1 file in the path I indicated above

launch two different apk from one android project

I want to launch two different android apps from one neutral project but the installed app will be only neutral one, and in that there will be two different buttons to launch(open in that app only) resp. project.
you need use flavores in gradle.
apply plugin: 'com.android.application'
android {
defaultConfig {
//...
}
buildTypes {
//...
}
productFlavors {
app1 {
// config for app 1
}
app2 {
// config for app 2
}
}
}
dependencies {
//...
}
see this link for learn about flavors

Build type specific folder not recognized for a product flavor

I have configured my project to have multiple product flavors. I have the following code in my module build.gradle:
android {
// Rest of the configuration omitted for clarity
buildTypes {
debug {
// ...
}
release {
// ...
}
}
productFlavors {
paid
free
}
}
If I create a file (any file: Java, resources, ...), in the paid, free, debug or release, it is recognized by Android Studio and I can use it in my project.
However, if the same file is created in paidDebug (or a similar folder) it is not recognized in Android Studio. Do I need any extra configuration for this to work? Is this not supported (yet)?
Source code files with the same name should be placed in all of the alternative source sets (but not in the 'main').
Either:
app/src/free/java/com/domain/myapp/MainActivity.java
app/src/paid/java/com/domain/myapp/MainActivity.java
Or:
app/src/freeDebug/java/com/domain/myapp/MainActivity.java
app/src/freeRelease/java/com/domain/myapp/MainActivity.java
app/src/paidDebug/java/com/domain/myapp/MainActivity.java
app/src/paidRelease/java/com/domain/myapp/MainActivity.java
Resource files with the same name can be placed in any source set, including 'main'.
app/src/main/res/layout/activity_main.xml
app/src/paidDebug/res/layout/activity_main.xml
app/src/paidRelease/res/layout/activity_main.xml
In this case, when building the 'free' flavor, the layout file from 'main' set will be used. But, during the build of the 'paid' flavor, the specific version of the layout will be used.
You can specify specific source directories in your build.gradle file. For example, to add testFreeRelease to unit test sources and testFree to android integration test sources:
android {
[...]
sourceSets {
main.java.srcDirs += 'src/main/java'
testFreeRelease.java.srcDirs += 'src/testFreeRelease/java'
androidTestFree.java.srcDirs += 'src/androidTestFree/java'
}
}
This also works for Kotlin. Just switch java with kotlin.

Separating integration tests from unit tests in Android Studio

I'm trying to separate out integration tests in Android Studio 0.9.
I have added the following to the build file:
sourceSets {
integrationTest {
java.srcDir file('src/integrationTest/java')
}
}
task integrationTest(type: Test) {
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}
I've run into a couple of issues:
The task will run but it doesn't have the rest of the project files available so I get errors about missing classes. There are some Java specific solutions I've found such as:
http://selimober.com/blog/2014/01/24/separate-unit-and-integration-tests-using-gradle/
https://blog.safaribooksonline.com/2013/08/22/gradle-test-organization/
But I haven't been able to figure out how to get this to work with Android Studio. Various combinations of main and main.output and playing around with dependencies don't seem to work, I get errors like:
Error:(33, 0) Could not find property 'main' on SourceSet container..
Which makes sense as the android plugin defines its own source sets, but these don't work either.
The IDE doesn't recognise the directory as a test source directory. For testing purposes I changed the source set name to androidTest and it correctly gets the green folder icon and the tests are run along with the existing unit tests that are already defined in androidTest.
#sm4's answer works indeed for a Java module (with apply plugin: 'java'), but unfortunately not for Android application (apply plugin: 'com.android.application') nor Android library modules (apply plugin: com.android.library).
But I have found a workaround:
Create the folders for your integration tests:
src/integrationTest/java
src/integrationTest/res
Add the sourceSets for your new folders:
sourceSets {
integrationTest {
java {
srcDir file('src/integrationTest/java')
}
res {
srcDir file('src/integrationTest/res')
}
}
}
In a pure Java module the java folder would now turn green and the res folder icon would change. In an Android application/library module it does not.
Now create a product flavor identically named as the folder configured in the sourceSet, and it works!
productFlavors {
integrationTest {
}
}
And to put a cherry on top:
configurations {
integrationTestCompile.extendsFrom testCompile
}
I've done exactly this kind of separation in Gradle, but for a pure Java project, not Android. You are not specifying the classpath in source sets, which I think is the issue. Here's the relevant part of the build.gradle:
sourceSets {
integration {
java {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integration/java')
}
resources {
srcDir 'src/integration/resources'
}
}
}
configurations {
integrationCompile.extendsFrom testCompile
integrationRuntime.extendsFrom testRuntime
}
task integrationTest(group: "verification", type: Test) {
testClassesDir = sourceSets.integration.output.classesDir
classpath = sourceSets.integration.runtimeClasspath
}
integrationTest.dependsOn testClasses
IntelliJ idea picks up the folders under src/integration if they have the standard names (java, resources).

Categories

Resources