Create your first custom Gradle Plugin for Android — Part 1: basic setup

Magicbluepenguin
6 min readMay 3, 2020

--

A hands on tutorial to get started with adding custom functionality to your Android builds using Kotlin

The introduction of Gradle as the preferred build tool for Android a few years back opened up a lot of possibilities for Android developers to make their build scripts more efficient and capable. Gradle is a flexible, powerful tool that — in the right hands — can greatly increase productivity by automating many of the otherwise repetitive manual tasks that developers need to contend with everyday.

There is a problem with this however. Gradle is also a big, scary monster that most sane people would prefer to never have to deal with. Yet if I will have done my job correctly, by the end of this write-up I will have done my bit to demystify Gradle and tease your curiosity as to the possibility offered by this tool.

While I am by no means an expert, the following is an attempt to put together a set of minimum instructions needed to create a basic custom Android Gradle plugin with Kotlin. Because a lot of this information is disseminated among different versions of the documentation, tutorials and personal expertise of people who took time out of their day to help me whenever I met a dead end, I hope that by putting this all in one place I can help those who come after me overcome the initial hurdles and quickly get started in their plugin-building journey.

Now, something I haven’t yet touched upon is, what is a plugin? As per the Gradle documentation, a plugin is defined as follows:

“A Gradle plugin packages up reusable pieces of build logic, which can be used across many different projects and builds. Gradle allows you to implement your own plugins, so you can reuse your build logic, and share it with others.”

One can think of a plugin as a separate app whose job is to add scripts (Tasks) to your project that modify it in some useful way. There’s really not much else to it. So now let’s move on to building one!

Basic Set-up:

As the official documentation only focuses on either creating a plugin as a standalone project or within the application’s build script, this tutorial will instead focus on the third use case, which I think is very useful for most real-life projects: creating a plugin as a standalone module inside our Android project. More information can be found here: https://docs.gradle.org/current/userguide/custom_plugins.html

Also, if you want to download the code shown below, you can get it from Github.

Start by opening the project in which you wish to build your custom plugin. If you don’t already have one or just want to follow along then create a new project. As I am starting from scratch I will let Android Studio do this for me. The main module of my project will be an application containing a single empty activity:

Next I will switch to Project view and create a new directory inside my project called buildSrc:

The naming here is important as Gradle will now recognise our directory as the source for our custom scripts and will set-up the plumbing it needs inside it. To make this happen click build -> Rebuild project. Once that is complete you will find that the `buildSrc` directory has been enriched with a few extra generated subdirectories:

Next we’ll need to add our new module to the project’s settings. Open settings.gradle file and modify it to include our plugin module. The contents of the file should now look something like this:

After letting Gradle sync, your buildSrc module should be correctly marked as a source directory for this project:

This is it for the initial setup. Next we’ll need to set up the dependencies for the plugin module itself.

Plugin Set-up:

Start by adding a build.gradle file inside the buildSrc directory. The file should contain the following:

Once you’ve done this you’ll need to create the basic directory structure to contain your plugin code. This is the familiar src.main.java that can be found in most Android projects. Just add the directories and Android Studio should mark them as source folders automatically.

The inside of your buildSrc module should now look something like this — plus or minus generated build folders:

Coding the Plugin:

Next — the moment we’ve all been waiting for — we can now start writing the plugin itself!

Create a new class — I’ll call mine MyFirstPlugin. This should extend the org.gradle.api.Plugin interface. This interface has a single apply method in which we can add all our magic:

As we want to have access to the Project object, we specify this as the plugin’s parameter so that Gradle will provide this for us in the apply method. But before we can manipulate this, we’ll first need to make sure that we are in fact dealing with an Android project. The following 2 extensions will do that for us, along with allowing us to access the project variants, which we will later need to make that our tasks correctly support all build variants:

Next, let’s build our task. This will be a simple task that adds a file to our application’s root directory. This is probably not a worthy real-world example, but it should be enough to demonstrate all the moving parts needed to create a basic custom plugin:

Wiring and running the Plugin:

Next we still need to perform 2 more steps before we can actually see our work in action. First, register the plugin by adding the following to the build.gradle file inside our buildSrc module:

This will make the plugin available to our application — and that’s where we’ll go next. Open the build.gradle file in your application project and add the plugin as follows:

You’re now done. After you sync the project you should now be able to see a new folder in the Gradle window containing the tasks you just created:

Double click on either of them and the result will be a new file called myfirstGeneratedFile.txt being created inside your project’s main directory. Take a moment to congratulate yourself, you’ve just created your first custom Gradle plugin!

Where to go from here:

Clearly the plugin we’ve created so far isn’t very useful. We could extend it to actually do something for us, like generating changelogs, pulling custom dependencies from non-Gradle APIs or generating resources from file or a remote repository. This last use case in particular is what we’ll start to dive into in Part 2 of this tutorial.

--

--