Advanced Android Flavors Part 2 — Enter Flavor Dimensions

This is the second article in my ‘Advanced Android Flavors’ series.
The first one is here.
The third one is here.
The fourth one is here.
The fifth one is here.
Adding Dimensions
Now that we have the basics down, it’s time to spice things up. I want to add the ability to configure which server the app communicates with. We have a choice of either dev, staging, or production.
We want to avoid creating a flavor for every possible client-server combination. That’s exactly what Flavor Dimensions do for us.
Flavor Dimensions allow us to define groups of flavors. Gradle creates every combination between these groups for us. No need to mix and match by hand.
Let’s test it out. I’ll add our three new server flavors and create our new dimensions (additions marked in bold):
android {
//...
flavorDimensions "client", "server"
productFlavors {
client1 {
dimension "client"
applicationIdSuffix ".client1"
}
client2 {
dimension "client"
applicationIdSuffix ".client2"
}
dev {
dimension "server"
}
staging {
dimension "server"
}
production {
dimension "server"
}
}
In the build variants menu we now have six flavors to choose from. Each has been created for us by Gradle. They are:
- client1Dev
- client1Staging
- client1Production
- client2Dev
- client2Staging
- client2Production.
Smarter Flavor-Specific Code
Remember how to add flavor-specific code? It works exactly the same with the added value of having it be a part of every combined build variant. Code inside the client1 is included in client1Dev, client1Staging, and client1Production configs. We can add code to the production folder and it will be included in client1Production and client2Production.
Now our folder structure can look something like this:
YourAndroidProject/
app/
src/
main/
<part of all builds>
client1/
<included in client1Dev/client1Staging/client1Production>
client2/
<included in client2Dev/client2Staging/client2Production>
dev/
<included in client1Dev/client2Dev>
staging/
<included in client1Staging/client2Staging>
production/
<included in client1Production/client2Production>
No need to copy/paste our code. By placing the right file in the right folder, Flavors have us covered. Think of how many errors we are avoiding by not creating these build variants ourselves.
But it doesn’t end there. Let’s say that the client1 variant needs some specific logic only for its production version. Well, we can create a new folder and name it client1Production. Code placed inside it will be included only in the client1Production build variant:
YourAndroidProject/
app/
src/
main/
<part of all builds>
client1/
<included in client1Dev/client1Staging/client1Production>
client2/
<included in client2Dev/client2Staging/client2Production>
dev/
<included in client1Dev/client2Dev>
staging/
<included in client1Staging/client2Staging>
production/
<included in client1Production/client2Production>
client1Production/
<included only in client1Production>
As you can see, with Flavor Dimensions, we’re pretty much covered for any standard Android application project. You can create whichever complex build variants your heart (or product manager) desires.
We’ve been talking about Android application projects so far. But everything I mentioned also applies to Android library projects. Which brings us to the last piece of the puzzle. How do we propagate flavors from an application project into a library project?
Up next: Flavorful Libraries