Gradle Tutorial for Android: Getting Started
In this Gradle Build Script tutorial you’ll learn the basic syntax in build.gradle files generated by Android Studio. You’ll also learn about gradlew tasks, build types, product flavors, build variants, and how to add additional information such as the date to the APK file name. By Irina Galata.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Gradle Tutorial for Android: Getting Started
35 mins
- What is Gradle?
- Getting Started
- Project-level build.gradle
- Module-level build.gradle
- Finally, settings.gradle
- Groovy vs. Kotlin in Gradle
- Why Kotlin
- Mastering the build: Gradle Commands
- What is gradlew
- gradlew tasks
- gradlew assemble
- gradlew lint
- Managing Dependencies
- Gradle Dependency Configurations
- Ready to Publish: Working with Product Flavors and Build Types
- Build Types
- Build Signing
- Build Flavors
- What is a Build Variant
- Creating Tasks
- Creating Custom Plugins
- Where to Go From Here
What is a Build Variant
From the output above, what you’ve actually generated are different build variants, which are a combination of build types – debug and release and build flavors – free and paid. That is to say, you have four possible build variants – paidDebug, paidRelease, freeDebug and freeRelease.
Great! You’ve got two different build flavors, however, differing names isn’t enough for you to profit from. Instead, you’ll configure your app’s behavior based on the flavor type!
Declare a constant for the paid flavor right below the declaration of ProfileActivity
class:
companion object {
const val PAID_FLAVOR = "paid"
}
Add the following function to ProfileActivity
:
private fun isAppPaid() = BuildConfig.FLAVOR == PAID_FLAVOR
You can now check if a user is using a paid version of the app. Depending on the result of this check, you’ll enable or disable some functionality visible to your user so they can clearly see what version they’re using in-app.
Add these strings to the strings.xml file:
<string name="free_app_message">Hi! You\'re using the free version of the application</string>
<string name="paid_app_message">Hi! Congratulations on buying
the premium version of the application</string>
Add the following functions below isAppPaid()
:
private fun showMessage() {
val message = if (isAppPaid()) R.string.paid_app_message else R.string.free_app_message
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}
private fun togglePhotosVisibility() {
extraPhotos.visibility = if (isAppPaid()) View.VISIBLE else View.GONE
restriction.visibility = if (isAppPaid()) View.GONE else View.VISIBLE
}
Add these functions invocations in the onCreate(savedInstanceState: Bundle?)
function:
showMessage()
togglePhotosVisibility()
Now, your user will see a different greeting message and will be able to view the whole photo feed or just some of the photos depending on the app version.
Select the freeRelease build variant in the window below:
Build and run the project (you may first need to choose the app build configuration in the drop-down next to the Run button):
You should see that the functionality of the app is restricted and the message with a corresponding text is shown.
Select the paidRelease option, and run the app again:
If a user buys your app, they’ll be able to access its full functionality.
Creating Tasks
Sometimes you need your build system to do something more complicated or customize the build process in some way. For example, you may want Gradle to output an APK file containing the build date in its name. One possible solution to this is to create a custom Gradle task.
Add the following code in your module-level build.gradle file at the same level as android
block:
// 1 task addCurrentDate() { // 2 android.applicationVariants.all { variant -> // 3 variant.outputs.all { output -> // 4 def date = new Date().format("dd-MM-yyyy") // 5 def fileName = variant.name + "_" + date + ".apk" // 6 output.outputFileName = fileName } } }
Here’s what’s is going on:
- You define an
addCurrentDate()
task. - You iterate through all the output build variants.
- You iterate over all the APK files.
- You create an instance of
Date
and format it. - You create a new filename appending the current date to the initial name.
- You set the new filename to current APK file.
Now you need to execute this task at a specific point of the build process. Add the following code below the task addCurrentDate()
block:
gradle.taskGraph.whenReady { addCurrentDate }
The task specified in the whenReady
block will be called once when the current graph is filled with tasks and ready to start executing them. Here, you specify the name of your addCurrentDate
task.
Now, go back to the command line and make sure you’re in the root directory. Run the following command to assemble a build:
./gradlew assemblePaidRelease
After the task has completed, go to the output directory and check if the build has been named correctly:
cd app/build/outputs/apk/paid/release/
ls
You should get a similar output:
output.json paidRelease_12-11-2017.apk
If your task executed correctly, all your builds will be named with this convention.
Creating Custom Plugins
Usually it’s a good idea to factor out your code into smaller pieces so it can be reused. Similarly, you can factor out your tasks into a custom behavior for the building process as a plugin. This will allow you to reuse the same behavior in other modules you may add to your project.
To create a plugin, add the following class below the addCurrentDate
task in the module-level build.gradle file:
class DatePlugin implements Plugin<Project> { void apply(Project project) { project.task('addCurrentDatePluginTask') { project.android.applicationVariants.all { variant -> variant.outputs.all { output -> def date = new Date().format("dd-MM-yyyy") def fileName = variant.name + "_" + date + ".apk" output.outputFileName = fileName } } } } }
Add the name of your plugin at the top of this file along with the other apply plugin
definitions:
apply plugin: DatePlugin
Conceptually, the code in the plugin is doing the same thing as the task – you’re still modifying the names of the output files. The only difference is that you define a class which implements Plugin
and its single method apply(Project project)
.
In this method, you’re adding your plugin to the target – Project
. By calling the task(String name, Closure configureClosure)
method you’re creating a new task with a specific name and behavior and adding it to the project.
Now modify the whenReady
block to call a new task:
gradle.taskGraph.whenReady { addCurrentDatePluginTask }
and remove the task addCurrentDate()
block you added earlier.
Now you can verify that this plugin is doing the same thing like the task. Assemble a new build and verify the APK filename:
./gradlew assemblePaidRelease
cd app/build/outputs/apk/paid/release/
ls
output.json paidRelease_12-11-2017.apk
Where to Go From Here
You can download the final project here.
The Android Gradle plugin 3.0 contains some significant differences from previous versions. So it’s worth reviewing the changelog.
Also, if you’re insterested in the Gradle Kotlin DSL, here you can find a list of usage examples to get familiar with it.
I hope you’ve enjoyed this Getting Started with Gradle tutorial! Don’t forget to leave your feedback and feel free to ask any questions in the comments below :]