196

I am converting one of my apps to Gradle and would like to use the new build flavor features to have a paid and a free ad based flavor.

I want only the ad based version to depend on the admob SDK.

My build file looks like this:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.5.+'
    }
}
apply plugin: 'android'

repositories {
    mavenCentral()
}

android {
    compileSdkVersion 18
    buildToolsVersion "18.0.1"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 18
    }

    productFlavors {
        Pro {
            packageName "de.janusz.journeyman.zinsrechner.pro"
        }
        Free { 
            dependencies {

            }
        }
    }
}

dependencies {
    compile 'com.android.support:support-v4:18.0.+'
    compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
    compile fileTree(dir: 'libs', include: '*.jar')
}

Is there a way to configure the dependency in the free product flavor to have its own libs folder that is merged with the main libs folder that contains general libraries for both flavors?

If this is possible how would I define this folder?

Janusz
  • 187,060
  • 113
  • 301
  • 369
  • visit this thread: http://stackoverflow.com/questions/24860659/multi-flavor-app-based-on-multi-flavor-library-in-android-gradle/24910671#24910671 – Ali Aug 01 '14 at 21:19

7 Answers7

219

To define a flavor specific dependency you can use proCompile instead of compile in your dependency section. When you run gradle properties you get an overview of automatic created configurations.

The correct build file looks like this:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
    }
}
apply plugin: 'com.android.application'

repositories {
    mavenCentral()
}

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 22
    }

    productFlavors {
        pro {
            packageName "de.janusz.journeyman.zinsrechner.pro"
        }
        free { }
    }
}

dependencies {
    compile 'com.android.support:support-v4:22.2.0'
    freeCompile 'com.google.android.gms:play-services-ads:7.5.0'
}
Sébastien
  • 13,831
  • 10
  • 55
  • 70
Rene Groeschke
  • 27,999
  • 10
  • 69
  • 78
  • 2
    I'm trying this and getting this error, `Error:(28, 0) Build script error, unsupported Gradle DSL method found: 'glassCompile()'!` (The flavor I'm trying to add a dependency to is "glass".) – nmr Jun 10 '14 at 20:20
  • 21
    Ahh, looks like you have to move the `dependencies` block below the `android` block. How intuitive. – nmr Jun 10 '14 at 20:22
  • 15
    Note that the `xxxCompile` closures Gradle generates will not work if the flavor name starts with a capital letter. – Jarett Millard Jan 21 '15 at 17:44
  • 2
    "packageName" should be "applicationId" – Apperside Apr 14 '15 at 07:49
  • 8
    How do you handle not calling the Ad classes? – Jared Burrows Jun 13 '15 at 19:55
  • @JarettMillard and note the difference! "compile" it's without flavors but when it's for flavors it's "Compile" with capital (or camelCase) – firetrap Sep 19 '15 at 18:11
  • 2
    @JaredBurrows put different versions of the classes that call the Ad classes in the different flavors. Probably it's better to have a single central class where you call those. – Stephan Nov 24 '15 at 14:36
  • this does work but for release builds i'm getting error `java.lang.NoClassDefFoundError: com.facebook.applinks.FacebookAppLinkResolver$1 at java.lang.Class.classForName(Native Method)` i think proguard is creating this issue. – Muhammad Babar Jul 20 '16 at 06:06
  • What if I want to remove the dependency for release builds, but leave it for debug builds? – Bitcoin Cash - ADA enthusiast Jan 28 '17 at 07:23
  • 1
    I've just upgraded to Andorid Studio 3.0 and I noticed that `dependencies` section no longer needs to be below `android` section in build.gradle - I was able to stipulate `debugCompile` even though my dependencies are listed above the android section. @Tiago use `debugCompile` – Someone Somewhere Nov 15 '17 at 14:18
  • Okay but what if I want to compile play-services dependency **instead of** support library dependency in `free` flavor? – Muhammad Muzammil May 09 '18 at 09:39
  • @SomeoneSomewhere I'm on AS 3.3 BETA 04 and you *still need* to put it below; we have 3 variants (debug/release/qa) and i was trying to use `qaImplementation 'some.dependency:1.0'` and it didn't work until I literally cut/paste the entire `android {` section (which includes `buildTypes` above `dependencies { `. `debugImplementation` and `releaseImplementation` worked, but if you define custom ones, they apparently must appear above. ¯\_(ツ)_/¯ – Martin Marconcini Nov 16 '18 at 20:27
48

Fast forward to mid-2018. You will need to add flavorDimensions.

android {
    ...
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    flavorDimensions "dimensionName"
    productFlavors {
        pro {
            dimension "dimensionName"
        }
        free {
            dimension "dimensionName"
        }
    }
}

dependencies {
    implementation 'com.android.support:support-v4:22.2.0'
    freeImplementation 'com.google.android.gms:play-services-ads:15.0.1'
}

Also, take note:

Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'. It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html

user1506104
  • 6,554
  • 4
  • 71
  • 89
16

Simple:

dependencies {

    ....
    ....

    gradle.startParameter.getTaskNames().each { task ->
        if(task.contains("free")) {
             implementation 'com.google.android.gms:play-services-ads:17.2.0'
        }
    }

    ....
    ....
}

or just:

FreeImplementation 'com.google.android.gms:play-services-ads:17.2.0'
nnyerges
  • 563
  • 4
  • 15
14

You need to manually add configuration for each flavor. Example

configurations {
    proCompile
    freeCompile
}

dependencies {
    compile 'com.parse.bolts:bolts-tasks:1.3.0'

    proCompile 'com.android.support:design:23.1.1'
    freeCompile 'com.parse:parse-android:1.12.0'
}
Arkadiusz Konior
  • 1,139
  • 13
  • 12
  • 2
    How to go on from there? How to activate the different configurations? Does this apply to the Android build only? Is it possible to that with non-Android builds? – koppor Apr 17 '17 at 19:47
11

Edit: I recommend using one of the other techniques!

An alternative to the accepted answer is this:

    ext {
        flavorType = ""
    }


    gradle.startParameter.getTaskNames().each { task ->

        if(task.contains("flavor1")){
            flavorType = "flavor1"
        } else if (task.contains("flavor2")){
            flavorType = "flavor2"
        } else {
            flavorType = "flavor3"
        }

    }

 if(flavorType == 'flavor1' || flavorType == 'flavor2') {
        compile 'com.android.support:support-v4:18.0.+'
    }
Jordy
  • 1,764
  • 1
  • 22
  • 32
8

If you use Gradle with Kotlin (build.gradle.kts), dependencies for custom flavors can be added as follows:

dependencies {
    "freeImplementation"("com.google.android.gms:play-services-ads:7.5.0")
}
Miloš Černilovský
  • 3,846
  • 1
  • 28
  • 30
  • It works but why is it a valid answer? Any source? – VaiTon Jul 19 '22 at 17:09
  • 1
    @VaiTon It is defined as an overloaded operator for String in DependencyHandlerScope.kt, looks as follows: `operator fun String.invoke(dependencyNotation: Any): Dependency? = dependencies.add(this, dependencyNotation)` – Miloš Černilovský Aug 29 '22 at 12:18
0

This way will work in multi-module projects

create a build gradle file (for example build_flavor_config.gradle) and define your config in it like this

android {
    flavorDimensions 'resource_type'
    productFlavors {
        create("flavor1") {
            dimension 'resource_type'
            versionName "$app_version_name - flavor1"
        }
        create("flavor2") {
            dimension 'resource_type'
            versionName "$app_version_name - flavor2"
        }
    }
}

and apply this gradle file for every module that you want for example app module or a feature module like this:

apply from: rootProject.file("build_flavor_config.gradle")

after sync project you can access to specific of implementation of each flavor like this:

flavor1Implementation("flavor1Library")
flavor2Implementation("flavor2Library")
Mahdi Zareei
  • 1,299
  • 11
  • 18