Building a Gradle plugin to support your Android SDK

ShahRukh
ProAndroidDev
Published in
6 min readJul 23, 2019

--

A Gradle plugin could help your SDK users in integration.

Objective

It happened to be that when we @ M800 were developing our new SDK, we needed some configuration file to be added to project root by the app developer. This config file will then be processed by our SDK, so we can initialize it properly. Something like what Google does with google-services.json via a plugin:

apply plugin: 'com.android.application'

In this article, I’m going to explain about building a very simple plugin which will read a json file and build some Android string resources from it.

Motivation

Truth be told, none of us here had any experience building a Gradle plugin before, so I was entrusted with the research and development task. I was driven by the excitement of building and learning something new. 🤩

Searching on Google about Gradle plugin development isn’t much of a help as it turns out that not many good resources are there and the official documentation is too much and not simple enough for a novice developer (like me) to understand.

Prerequisite

Obviously, you need to know Java, Gradle, and Android app development (to test the plugin) but other than that you need to go through this article https://docs.gradle.org/current/userguide/custom_plugins.htm to understand the basics of Gradle plugin development. In that article, you’ll learn about the files and methods I’m going to use now.

Let’s Build

The first thing that you’ll need to build the plugin is an IDE and you can’t use Android Studio so you can go here to download the IntelliJ IDEA if you don’t have it already.

Project Setup

  • Start a new project and select Gradle from the left menu then enable Java as well as Groovy from options on the right.
  • As the next step, you’re going to set the GroupId, ArtifactId and Version for your project.
  • You can just leave the next two screens to the defaults.

As you first open your project build.gradle file, you see a tip like this, just click on Ok, apply.

Now you’ll have to right-click on your root project folder in IntelliJ IDE and create a new directory src/main/groovy(if it’s not there already). If the groovy folder doesn’t automatically turn blue, right-click on it and mark it as source root.

I went as the documentation said, so I added these dependencies in build.gradle and note that you might have to sync gradle manually.

dependencies {
compile gradleApi()
compile localGroovy()
}

Now add a package in groovy folder and name it com.project.sdk
In this project, make a new groovy file ServicesPlugin.groovy like.

class ServicesPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
}
}

And a task file to do the actual work.

public class ServicesTask extends DefaultTask {
@TaskAction
public void action() throws IOException {

}
}

You should also add these line in the same gradle file.

gradlePlugin {
plugins {
greetingsPlugin {
id = 'com.project.sdk'
implementationClass = 'com.project.sdk.ServicesPlugin'
}
}
}

You’ll need the JSON parsing so add this to your gradle file dependencies.

implementation 'com.google.code.gson:gson:2.8.5'

So now my complete gradle file looks like this:

plugins {
id 'java-gradle-plugin'
id 'groovy'
}
group 'com.project.sdk'
version '1.0'
sourceCompatibility = 1.8repositories {
mavenCentral()
}
gradlePlugin {
plugins {
greetingsPlugin {
id = 'com.project.sdk.your-plugin-name'
implementationClass = 'com.project.sdk.ServicesPlugin'
}
}
}
dependencies {
compile gradleApi()
compile localGroovy()
implementation 'com.google.code.gson:gson:2.8.5'
}
apply plugin: 'maven'uploadArchives {
repositories {
mavenDeployer {
repository(url: uri('/Users/shahrukhahmed/Development'))
}
}
}

Now you need to add another file which will act as a map to the class of your plugin implementation. So right-click on “main” and create “a new directory” resources/META-INF/gradle-plugins

and in this directory, add a new file com.project.sdk.properties

The content of this file is simple. It’ll just be used to define the file which implements the plugin.

implementation-class=com.gradle.ServicesPlugin

You’ll have to first check this Gradle plugin locally. So, add these to your project gradle.

apply plugin: 'maven'uploadArchives {
repositories {
mavenDeployer {
repository(url: uri('<your-local-repo-location>'))
}
}
}

After syncing, you’ll have a gradle task like this

and when you run this task, it’ll publish your plugin to your specified directory. Looking in the package, it’ll look like this:

This is a functional plugin and you can just use it directly in your app by adding this to your project gradle:

buildscript {
repositories {
maven {
url uri('<your-local-repo-location>')
}
}
dependencies {
classpath group: 'com.project.sdk', name: 'your-plugin-name', version: '1.0'
}
}

and this to your app gradle:

apply plugin: 'com.project.sdk.your-plugin-name'

but this will not add any gradle tasks to your app right now as we haven’t added anything yet in the ServicesPlugin and ServicesTask classes that we created earlier.

Implementation

As I’ve mentioned before, this sample plugin will read an example.json file from your app level directory and parse it then add the parsed values to your String resources. So the next task in hand is to make changes in these files.

This article will not explain what each line is doing in these files, but they are pretty straight forward. So the file will look like this:

Clone project https://github.com/shahrukhamd/SampleGradlePlugin

After this, if you click on uploadPlugin task again in your plugin project, it’ll publish the latest code to your local repository and you can then sync your application gradle to add this plugin tasks.

Testing

When you do that, you’ll be able to find a task like this in your app:

That’s basically all there is to build and use this plugin. All you need now is to test it with an actual file. In our case, I need a file named example.json in the app directory.

Content of this file is pretty simple, just some random name-value pairs.

{
"context_url": "https://json-ld.org/contexts/person.jsonld",
"id": "htt6515dbpedia12org8749esource094JohnLennon",
"name": "John Lennon",
"born": "1940-10-09",
"spouse": "http://dbpedia.org/resource/Cynthia_Lennon",
"enable_featuer_1": "true",
"enable_featuer_2": "false",
"enable_featuer_3": "true"
}

Now if you run your gradle task, DebugYourPluginTaskName you’ll see a new values.xml file in your app’s generated folder.

If you open this file, you’ll have the Android String resources:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="born" translatable="false">1940-10-09</string>
<string name="context_url" translatable="false">https://json-ld.org/contexts/person.jsonld</string>
<string name="enable_featuer_1" translatable="false">true</string>
<string name="enable_featuer_2" translatable="false">false</string>
<string name="enable_featuer_3" translatable="false">true</string>
<string name="id" translatable="false">htt6515dbpedia12org8749esource094JohnLennon</string>
<string name="name" translatable="false">John Lennon</string>
<string name="spouse" translatable="false">http://dbpedia.org/resource/Cynthia_Lennon</string>
</resources>

And that is what was required from this plugin, right?

As it turned out, building a plugin is not as hard as I initially thought. Sure it was initially a little confusing but that was because of the unavailability of the right articles. I wrote this article to fix that exact problem.

You can clone this project from here:

Do press the clap 👏🏻 button if you liked this article and wanna appreciate my efforts.

--

--

The Android guy @ Jodel | Android Apps | SDK | Shutterbug | Dreamer | Thinker www.shahrukhamd.com