Whenever you’re working with Gradle-based projects you probably noticed things like apply plugin: ‘java’ at the top. Some libraries even require you to apply their own plugins, in fact, the android tools are a plugin by themselves! Of course Gradle plugins are not limited to only Android projects, they’re not even limited to Java projects. You can for example use a plugin for Kotlin, while the plugin itself may be written in Groovy.
The best way to explore the plugins is, of course, creating one of our own. I’ll describe creation of a simple plugin, one that will simply add some dependencies to the project, as well as their repository. Starting out is fairly simple, we’ll be creating a new Android project, then add a new Java module to it. Before we can start we need to add some dependencies to the Java module:
The gradleApi() dependency provides classes like Plugin, which we’ll need later on. We also rely on Android build tools plugin, so we can check if android-specific plugins are applied. If you’re writing a plugin that is specific to Java or some other language these aren’t required. I’ve also added a set of dependencies for testing, so that we can properly test our plugin. Now we can begin! We’ll start by creating the actual plugin class:
That’s all you need to do in code for your custom plugin, the language used here was Java, but the same can be done in Groovy or Kotlin, or other JVM languages. This, however is not enough for the plugin to be used, we haven’t declared it anywhere after all! If you’ve followed my annotation processing post (https://equaleyes.com/blog/2017/09/04/annotation-processing/), then you probably already know that you’ll also need to add some data to META-INF. This can be easily achieved, simply create a file in <module_dir>/src/main/resources/META-INF/gradle-plugins. The file name should be something like demo_plugin.properties. The contents of this file should read implementation-class=com.equaleyes.demoplugin.DemoPlugin. As you can probably tell, the right side indicates the fully-qualified class name of the plugin class. That’s it! Our plugin is now usable. Since it doesn’t do anything, there’s no real point in running it yet. We better start adding some functionality! We can do that by simply adding code to the apply function in our plugin class. In our case, we’ll add some validation first:
In requireAndroidPlugins we assert that either the application or android-library plugin is present, thus making sure that the plugin is applied to an Android project. GradleException thrown here will appear in the build log, stopping the build. In the second function, requireTransformAvailable we assert that Transform class is available, this is not really required for a plugin that only adds dependencies, it’s used in bytecode processing. Note that the functions are set to be package-private, this way we can easily test them one by one.
Now we can get to adding the repository and dependencies. It’s actually really simple, just like adding items to a list:
That’s it! After applying the plugin, the project will have these dependencies present. Of course, in some cases you might also want to check if kotlin-android plugin is present, to use kapt instead of annotationProcessor.
Now we need to make sure our plugin is usable. By far the easiest method for developing a plugin is by writing tests, but eventually you’ll want to use it in a project either way. We can use it in our project by first publishing it to a local maven repository, and once we’re comfortable with it, we can upload it to a repository. There’s a simple guide for uploading at https://plugins.gradle.org/docs/publish-plugin, but this only covers uploading the plugin to Gradle. Well add the following:
Additionally, we need to add mavenLocal() to our repositories. Now we can run publishToMavenLocal task. All that’s left now is to apply the plugin. We need to add our plugin to classpath in root build.gradle file. We can do this by adding classpath ‘group.name:name:version’, then to our application build.gradle we simply add apply plugin: ‘name’ at the top and we’re done! We’re now using our very own plugin!