How to Build Multiple Apps With a Single Android Project: 2021 Android Productivity Hack

AnDroid Developer
7 min readJul 29, 2021

--

Android product flavors is a powerful feature using which a developer/team can easily build different versions of a single app, but easily customized to keep similarities and allow divergence as and when necessary.

Hey my gorgeous friends… How are you? Yon won’t find anything so new, rather in this article I am going to talk about a powerful feature of Android Studio that makes life so simple and yet not used much. Yes, we are going to talk about Android Product Flavors.

Back in 2018, I was building similar apps and I did not know about this feature of Android Studio. I had tough times maintaining all the apps. With help of Android product flavors you can maintain multiple apps in a single project and have shared code and resources for all your apps well organized in a single project. Want something more? You can set up CI/CD to test and build all the flavors using CI/CD tools and frameworks, so you don’t have to manually run tests, build and deploy all the apps one by one. Of course you will have to upload the `.aab` or `.apk` files to google play-store. By the way if you are aware of any hack to automate that as well, please let me know in the comments.

If you are already familiar with Android Product Flavors, you can skip to the next section where I talk about some of the pitfalls and quick fixes. If you are using or want to use google services for your Multi-flavored project, please read this answer on StackOverflow.

What are Android flavors When should you use them?

Before we discuss how to build multiple flavors of an app, it’s important to understand why and when you might need multiple flavors. As an app developer, you can run into the “not so unique” situation where you (or your team) would like to release a given app using a new brand name, logo and/or theme, along with some minor feature differences. Assuming you intend to maintain the different apps, and release them on Google’s Play Store, this can turn into a major maintenance headache very quickly. Another more frequently encountered scenario is when you want to maintain a free version and a pro version with some additional features. In both of these scenarios, having ability to maintain multiple apps in a single project with shared code base and resources is invaluable.

The naive way handle above scenario might involve having a base/core project and separate projects for each version, which is far from ideal, and will lead to errors and projects not having the complete new changes.

Another way to achieve this can involve building the core of the project as a library, and then creating different projects that reference the library core. While this will theoretically work, it would be very difficult to achieve, since what you will be doing is actually trying to build an app as a library.

Thankfully, there is an easier and completely painless way to build and maintain multiple versions of an app as described above, and it is built into Android Studio and Gradle by default. This is called “flavors.”

Using multiple flavors, a developer/team can easily build different versions of a single app, but easily customized to keep similarities and allow divergence as and when necessary.

In addition to flavors, there is another very important concept regarding building android apps, called “build types”.

A build type applies settings relating to the build and packaging of the app, such as if it’s debuggable and the signing keys. The default build types are debug and release. In contrast, a flavor can specify features, device and API requirements (such as custom code, layout and drawables), and minimum and target API levels among others.

The combination of build types and flavors forms a “Build Variant”. There is a build variant for every defined flavor/build type combination. Hence, if you have two flavors, called blueberry and raspberry, and two build types called debug and release, the Build Variants will be:

  1. blueberryDebug
  2. blueberryRelease
  3. raspberryDebug
  4. raspberryRelease

For a more in-depth and technical description of Build Variants, check out the Android Studio Build Variant user guide

Using Gradle flavors

Once you have opened up your existing Android project or created a new Android project, open app-level build.gradle file.

App level build.gradle file in Android view in Project Explorer

Add productFlavors block inside android block in app-level build.gradle file as shown below.

plugins {
... your plugins go here
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.1"
defaultConfig {
applicationId "your.application.id"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
... any other default settings
}
// ===========Define your product flavorsflavorDimensions 'default'
productFlavors {
Free {
dimension 'default'
applicationIdSuffix '.free'
}
Pro {
dimension 'default'
applicationIdSuffix '.pro'
}
}
// ===========Define your build typesbuildTypes {
debug {
minifyEnabled false
...
}
release {
minifyEnabled true
...
}
}
}
dependencies {
... your dependencies go here
}

Now Android Studio knows that you want to create 2 flavors of your app, one for called Free and other called Pro and two build types, which are debug and release by default. You can add as many flavors, flavor dimensions and build types as you wish to. So, far only difference between our flavors is that both have different package names, one ending in .free and other in .pro. Let us now see how to manage resources and source code for different flavors.

Resource Files

At this point, we know how to create different flavors with buildTypes but it isn’t enough in real-world we should be able to create resource and java files specific to each variant. First, let’s see how to create resource files for each flavor

Switch to project view in the left panel and then expand all directories until src and then right-click on src then navigate to

new > Folder > Res Folder

Then you’ll see a popup with two fields

  1. Target Source set is nothing but the source code directories for selected flavor.
  2. The New folder location is the location where the file will be created.

Similarly, we can create a directory for all flavored build types if necessary.

Observe that at the end of the above demo, a new line is added in build.gradle file with sourcesets block like below

sourceSets {
PaidRelease { res.srcDirs = ['src/PaidRelease/res', 'src/PaidRelease/res/'] }
}

Java Files

Creating a java directory for each flavor is similar to resource directories creation, the only difference is that we select a java folder instead of the res folder. Have a look

3rd Party library integrations for different flavors

The paid version has some extra features which require an additional library for paid flavor variants, so we should only include this library for paid variants. Library integrations can be done specifically to particular flavor variants, have a look

PaidImplementation ('com.squareup.picasso:picasso:x.x')

Combine the flavor name with implementation tag and import the library. Those library features will only available to specific flavors.

If you want to integrate Firebase or Google services associated with different projects in different flavors of your app, you can follow the solution provided here.

Woo! You did it. You have made it till this point and now you know what Android Product Flavors are, what are android build types and how they are so useful. I hope you enjoyed the post. If you have any other questions of suggestions, please post them in comments and I will try to address them. And wish you a very happy and healthy life and career ahead… Have a great day!

--

--

AnDroid Developer

This blog focuses on Technology articles related to Android Development