9.
Build Variants: Implementing Build Types
Written by Evana Margain Puig
In the following two chapters, you’ll learn how to create different versions of your app within the same project. Before you begin, you need to understand three terms: build variants, build types and build flavors. These three terms are often a source of confusion when releasing to the Google Play Store, especially if you haven’t played around with them. Time to dive right into learning what these terms mean:
-
Build types: In Android apps, build types usually refer to the environment in which you’re testing. By default, when you create an app in Android Studio from any of the templates, you get two build types: debug and release. If you’ve worked in tech companies, you may know there are usually more than those two. You can customize your build types to include other types such as QA, Release Candidate or RC, Pre-Prod or whatever fits your needs.
-
Build flavors: Apps often vary in ways besides environment-based differences. Flavors support these kinds of variations. For example, you can use flavors to handle:
- Having a paid version of your app vs. a free version.
- Having a version for each store you upload to, such as Amazon Appstore, Google Play Store and Samsung Galaxy Store.
- Using the same app for different products and customizing the assets to change the app’s look and feel.
- Build variants: Variants are the combination of build types and build flavors. For example, you can have a “dev paid” version of your app, which is a combination of the “dev” build type and “paid” flavor of your app. If you have both flavors and types, you’ll release variants when uploading to the Google Play Store or any other store.
Now that you have a clear understanding of what each of these terms means, you’ll start by learning how to implement build types throughout this chapter.
Why use build types?
By now, you understand build types at a high level. In short, it’s a build configuration that lets you differentiate versions of your app depending on the environment you’re targeting, such as development, testing or release. But from a high level, this may not sound like something special or different from a flavor. So take a look at precisely what a build type does behind the scenes.
Build types target configurations in your Gradle properties. For example, a build type can:
- Enable or disable debugging in your app.
- Sign the app with a production certificate if needed.
- Shrink or obfuscate your resources. For an in-depth understanding of this topic, take a look at Chapter 7.
Remember, you need at least one build type to build your app. Android Studio templates give you two by default.
Android Studio base build types
Take a look at PodPlay to see where you can find those default build types. Open the PodPlay project in Android Studio. In the Navigation panel’s Android view, navigate to Gradle Scripts ▸ build.gradle(Module: PodPlay.app). Look at the buildTypes group inside the android declaration.
There you’ll find two build types: debug and release, as shown in the image below:
Also, look at the tag above those build types, named defaultConfig. It defines the properties available to all buildTypes unless you override them inside the specific buildType.
If you create a project from scratch with an Android Studio template, you’ll only see the release build type defined, like in the image below:
Although you can’t see it, the debug type also exists by default. It isn’t mentioned since it uses all the configurations from the defaultConfig. If you want to change something in the debug build type beyond what you have by default, you can add it, as in the PodPlay example.
Switching build types in Android Studio
Android Studio has a Build Variants panel. Usually, you’ll find it at the bottom left of your screen as a closed tab. Tap it and you’ll see the panel. If you can’t see the panel there, go to View ▸ Tool Windows ▸ Build Variants as shown below:
You’ll find this panel:
Here, you’ll see a list of all the app modules with their current build variant. All the previously defined modules in PodPlay have the default release and debug build variants. Changing from one build variant to another requires a Gradle Build.
Note: In most projects, different modules within a single app all need to point to the same environment to compile. For example, if you select a release version on a module, you may also need to change all the other modules to release in the Build Variants window. Otherwise, you may get compile errors.
Implementing build types in your app
Now it’s time to put what you’ve learned into practice and create a new build type. Open your app module’s build.gradle located in Gradle Scripts ▸ build.gradle(Module: PodPlay.app). Below the release version closing bracket, add a build variant named qa with:
qa {
initWith debug
applicationIdSuffix ".qaTesting"
signingConfig signingConfigs.debug
}
For this new config, you define three parameters:
-
initWith: This parameter has the value debug, which means this version has all the properties the debug build type has, plus the ones defined inside the brackets.
-
applicationIdSuffix: This parameter has the value
.qaTesting, which, as the name implies, adds the suffix to your app’s installed package name. Adding this suffix facilitates installing more than one version of your app for testing on the same device. -
signingConfig: In this case, you set it to use the debug build’s signing configs because you aren’t uploading this version to a store. If you use a third-party service to distribute your app to testers, you may need to include another type of signing here.
Click Sync Now. Once Gradle finishes syncing, open Build Variants and choose qa for Podplay.app as shown below:
Once you change the build variant, Gradle will take a few seconds to sync. Build and run the app. Open the Logcat tab, and you’ll see the app’s package of is now com.raywenderlich.podplay.qaTesting in the logs.
As simple as that! No need to add anything complicated at all.
If you get errors (Optional)
If you had no trouble running the previous step, skip this section. Otherwise, keep reading.
If you didn’t download the starter project, there are a couple of lines that may cause a conflict in the build because you need to add the buildType to each of the modules defined in the app. You have two options for fixing this issue:
-
Go through each Module build.gradle and add the same build type you added.
-
Go to your Android Manifest and delete
<dist:module dist:instant="true"/>. In the app’s module build.gradle, where you added the build type, remove or comment the line with:dynamicFeatures = [':installTimeDeliveryExample', ':onDemandDeliveryExample', ':conditionalDeliveryExample', ':instantModuleExample'].
If you’re following along with this chapter’s ‘starter’, these lines are no longer there.
Now run a Gradle build to make this build type available by clicking the icon shown below.
Re-open the Build Variants panel. You’ll see the new build type and can change it, as in the image below.
Gradle DSL reference
PodPlay’s Gradle files are in a Groovy-based DSL. Groovy is a Java scripting language and DSL stands for Domain-Specific Language. You may find other apps have Kotlin based Gradle files. Either way, the configurations are similar.
The properties available for configuring your build type depend on the Android Gradle Plugin version you use. At the time of writing, the current release is 4.2.2. You can find the reference of Gradle files in the Android documentation at https://developer.android.com/docs by navigating to Reference ▸ Other Libraries ▸ Android Gradle Plugin:
You’ll see a page where they indicate the latest Android Gradle Plugin version.
Click Current Stable Release as shown in the image above. You’ll see a page that displays all the classes available in the plugin. Select BuiltType, and you’ll see the documentation for the BuildType class.
On this page, you can find all of the build variant’s properties. For example, isMinifyEnabled specifies whether to enable code shrinking for this build type. Code shrinking is important for your build types because while it makes debugging harder, it also optimizes code for distribution versions.
You may notice only a few properties listed in the documentation, and they don’t match the ones in PodPlay’s Gradle files. This is because there’s an inheritance. BuildType has access to all the properties in VariantDimension because, as you learned earlier, build types paired with flavors form variants. So, you can put the listed properties in the VariantDimension reference either in your build types or flavors depending on the app’s needs.
You can view all of VariantDimensions’ properties at https://developer.android.com/reference/tools/gradle-api/4.2/com/android/build/api/dsl/VariantDimension.
Release build type
It’s important to understand release type because it’s the version you’ll upload to the Google Play Store. Choose the release variant in the Build Variants Panel, and wait for the Gradle sync to finish.
You won’t see any errors when the build finishes but that doesn’t mean you’re done. Try to run the app with the Run button at the top of Android Studio. You’ll see an Edit Configurations dialog. You’ll also see the app version in the top bar has a small red x sign next to it:
That x means Android Studio still doesn’t know how to sign your app. In chapter 2, you learned how to create signing certificates. You need to add some here. The Edit Configurations dialog offers an option to Fix the problem. But you need to create the certificate first if you don’t have it.
Creating a release certificate (Optional)
Before doing this let’s review how to create the certificates for signing a release build as you learned in previous chapters.
In the top bar of Android Studio go to Build ▸ Generate signed bundle / APK, as in the image below.
In the dialog shown select Android App Bundle. Technically you can choose either, but Android recommends using Bundles and they will be soon the only accepted format in the Google Play Store, so go for this option. Click Next.
In the next screen supposing you don’t yet have a certificate for the app, click on the Create New button under the Key Store Path label.
Now fill in the fields one by one and save the information you input there because you will need it later:
- Key Store Path: Where in your local storage you want to save your certificate. I selected: ../Desktop/pod_play_key_example.
- Password: The pass of that key store. Always be sure to save both the keystore and this password in a safe place, if you lose them you won’t be able to update your app on the Google Play Store. For the purpose of this example and just so you don’t forget I suggest using pass123.
Note: Remember to always use safe passwords in any certificate, someone with unauthorized access could damage users devices through your app.
- Alias: A name with which you will identify the key, for example: pod_play_key.
- Password: Another, preferably different, password for the key itself. For the purpose of the example again use pass123.
- Validity: Just leave the default.
- In the fields below you only need to fill in one field, fill in the one that says First and Last name with your own.
Leave the rest of the fields empty. Take a look at the image below to see how the data should look now.
Click OK and the Key related fields should automatically have the information filled in as in the image below.
Click Next and you will see a list of your app’s Build Variants.
Select the release variant and click Finish.
Right after clicking the button a Gradle Build will start, wait until it finishes.
Fixing the release build problem
Now try to run the app again with the Run button at the top of Android Studio, with the release version selected. You’ll still see the app version in the top bar has a small red x sign next to it:
That means Android Studio still doesn’t know how to sign your app, even though you already created them. You now need to add them to the project.
Click on the icon with small red x, choose Edit Configuration and a dialog will come up with an option to Fix the problem.
Click on the Fix button.
With that, you’ll see a Project Structure dialog appear and a Signing Configs tab selected. The compiler will take them every time you choose that release build. Click on the + sign shown in the image below.
A small dialog with a text input will appear now, write release as the name of the build config.
Click OK and you will be back in the Project Structure dialog. Fill in the information with the data of the certificate you created in the last section Creating a Release Certificate. If you followed the example above then you will have:
- Store File: The file location of the certificate
- Store Password: pass123
- Key Alias: pod_play_key
- Key Password: pass123
This is how the dialog should look like now:
Then you can click OK and you will be back in the first dialog called Project Structure. Change to the tab called Default Config and locate the field called Signing Config and in the dropdown select the option $signingConfigs.release. Look at the image below for guidance.
With those changes, now you can run the app. Verify the app is working as expected.
Now navigate to Gradle Scripts ▸ build.gradle(Module: PodPlay.app). In this file you will notice some lines were added in order to have the certificate and credentials added automatically every time you build a release version. In the image below you will see the sections of the code that Android Studio added for you through the configuration steps.
Note: In the code above you are using a hardcoded path to the keystore. This is not a good practice because in the example above you are referencing a path that is specific to one developers machine, which will be different from developer to developer. Later in the book you will learn techniques to store this key safely and make it accessible for larger teams. In the meantime, keep in mind that you should not put it in a public repository because that will make it easy for a bad actor to get it, which will create a security issue for your app.
That’s all you need to know about build types! In the next chapter, you’ll build on this knowledge to create flavors that’ll make your build variants complete.
Key points
- Build variants are a compound output of build types and build flavors.
- Build types take care of your app’s Gradle configurations.
- You can create as many build types as your app needs.
- Most Gradle files are in a Groovy Based DSL, but some are written in Kotlin.
- The release build type requires a signing configuration that includes the release certificates.