Is there a way to have compile dependencies by multiple flavors in Android Studio (build.gradle)?
I have 2 flavorGroups, and in each 2 variants. Out of the 4 possible combinations I would like to be able to depend on a lib only if I'm both in latest and in free flavor. latestCompile or freeCompile works, but latestFreeCompile doesn't. this is the relevant part of my build.gradle:
android {
defaultConfig {
minSdkVersion 7
targetSdkVersion 19
versionCode 15
versionName "1.9." + versionCode
}
flavorGroups 'sdk', 'cost'
productFlavors {
latest {
flavorGroup 'sdk'
minSdkVersion 8
}
sdk7 {
flavorGroup 'sdk'
minSdkVersion 7
versionName android.defaultConfig.versionName + ".sdk7"
}
free {
flavorGroup 'cost'
}
pro {
flavorGroup 'cost'
}
}
}
dependencies {
// this works:
freeCompile files('libs/StartAppInApp-2.2.1.jar')
// and I would like something like this:
latestFreeCompile 'com.google.android.gms:play-services:4.1.32' // minSdkVersion:8
}
If I would use:
latestCompile 'com.google.android.gms:play-services:4.1.32'
then it would be included in latestPro as well (not needed) and if I'd use:
freeCompile 'com.google.android.gms:play-services:4.1.32'
then it would be included in sdk7Free as well (although it needs SDK 8)
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.
A build type determines how an app is packaged. By default, the Android plug-in for Gradle supports two different types of builds: debug and release . Both can be configured inside the buildTypes block inside of the module build file.
Simply open the gradle tab (can be located on the right) and right-click on the parent in the list (should be called "Android"), then select "Refresh dependencies". This should resolve your issue.
Configuration inheritance and composition For example the testImplementation configuration extends the implementation configuration. The configuration hierarchy has a practical purpose: compiling tests requires the dependencies of the source code under test on top of the dependencies needed write the test class.
As now described on the official Android Developers website, if you want to declare a dependency for a specific combination of product flavor AND build type you need to declare that configuration first.
For example for the free
flavor and the debug
type:
configurations {
freeDebugImplementation {}
}
dependencies {
freeDebugImplementation 'com.google.firebase:firebase-ads:9.8.0'
}
Note that if your app has multiple flavor dimensions, you must create the configuration corresponding to the full build variant (ALL flavors, then build type), like so:
flavorDimensions "money", "image"
productFlavors {
free { dimension "money" }
paid { dimension "money" }
picasso { dimension "image" }
glide { dimension "image" }
}
configurations {
freePicassoDebugImplementation {}
freeGlideDebugImplementation {}
}
dependencies {
freePicassoDebugImplementation 'com.google.firebase:firebase-ads:9.8.0'
freeGlideDebugImplementation 'com.google.firebase:firebase-ads:9.8.0'
}
I had the same problem. I resolved that with some gradle code in my build.gradle:
// global variables
ext {
buildType = ""
groupCost = ""
groupSdk = ""
}
def splitCamelCase(String word) {
def result = []
int nextStart = 0;
for (int i = 1; i < word.length(); i++) {
if(word.charAt(i).isUpperCase()) {
result.add(word.substring(nextStart, i));
nextStart = i;
}
}
result.add(word.substring(nextStart));
return result;
}
// start parameters
println "Start parametes: tasks = " + gradle.startParameter.getTaskNames()
gradle.startParameter.getTaskNames().each { task ->
// This line is needed to skip other projects' tasks
// You can safely remove it if you have only one project
if(!task.startsWith(':<your_application_name>:')) return;
def taskParts = splitCamelCase(task.split(":").last());
def groupCostPrefix = taskParts[taskParts.size() - 3];
def groupSdkPrefix = taskParts[taskParts.size() - 2];
def buildTypePrefix = taskParts[taskParts.size() - 1];
if("Debug".startsWith(buildTypePrefix)) {
buildType = 'debug';
}
else if("Release".startsWith(buildTypePrefix)) {
buildType = 'release';
}
else {
return; // do not process tasks that are not ending with proper build type.
}
if("Free".startsWith(groupCostPrefix)) {
groupCost = 'free';
}
else if("Pro".startsWith(groupCostPrefix)) {
groupCost = 'pro';
}
if("Sdk7".startsWith(groupSdkPrefix)) {
groupSdk = 'froyo';
}
else if("Latest".startsWith(groupSdkPrefix)) {
groupSdk = 'latest';
}
}
Then all you need is to add following code inside your 'dependencies' section:
if(groupSdk == 'latest' && groupCost == 'free') {
compile 'com.google.android.gms:play-services:4.1.32'
}
Same issue here, but Pawel's solution didn't work because gradle dependencies have other issues in which it starts building not only the selected flavors/build type, but all of them and it requires a more dynamic solution.
Still I found this issue tracker: https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=52962
There is also a reference to fixing the rebuild-all bug I mentioned above, but I didn't try it yet.
And implemented this solution (as per issue tracker reply #60):
Map<String, Dependency> customDeps = new HashMap<String, Dependency>()
customDeps.put('flavor1GrpXflabor1GrpYDebugCompile', dependencies.project(path: ':lib', configuration: 'debug'))
customDeps.put('flavor1GrpXflavor1GrpYReleaseCompile', dependencies.project(path: ':lib', configuration: 'release'))
customDeps.put('flavor2GrpXflavor1GrpYDebugCompile', dependencies.project(path: ':other_lib', configuration: 'debug'))
customDeps.put('flavor2GrpXflavor1GrpYReleaseCompile', dependencies.project(path: ':other_lib', configuration: 'release'))
....
configurations.all() { config ->
Dependency d = customDeps.get(config.name)
if (d != null) {
config.dependencies.add(d)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With