Gradle plugin for Android project

android
plugins

(Ackee) #1

Hello everyone,

I am trying to make a gradle plugin that would configure an Android project.

This is the build.gradle file of the plugin:

plugins {
    id("java")
    id("groovy")
    id("kotlin")
    id("java-gradle-plugin")
    id("com.gradle.plugin-publish") version "0.10.0"
}

dependencies {
    implementation gradleApi()
    implementation localGroovy()
    implementation "com.android.tools.build:gradle:3.2.1"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}

repositories {
    google()
    jcenter()
    mavenCentral()
}

I decided to write the plugin in Kotlin since almost noone in our company understands Gradle and Groovy enough to create anything useful and Kotlin makes things clearer to understand.

In Groovy it didn’t matter, but because Kotlin is strongly typed, I need a reference to the actual Android AppExtension to be able to configure it. I discovered that by adding dependency to com.android.tools.build:gradle:3.2.1 I can get the required reference with project.extensions.findByType(AppExtension::class.java). I then configure the Android extension, add some tasks and extensions etc.

I can build a jar and apply the plugin in the main project like this:

top-level build.gradle

buildscript {
    repositories {
        google()
        jcenter()
        mavenCentral()
        flatDir { dirs("../libs") }
    }

    dependencies {
        classpath("com.android.tools.build:gradle:3.2.1")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
        classpath(":plugin-1.5")
    }
}

allprojects {
   repositories {
        google()
        jcenter()
        mavenCentral()
    }
}
:app build.gradle

plugins {
    id("com.android.application")
    id("cz.ackee.gradle.plugin")
}

and the project is indeed pre-configured, custom extensions are available, everything works as expected.

I can also publish the plugin to https://plugins.gradle.org/ repository and use it in a project. Doing so, I don’t need to define flatDir {} and classpath() in the top-level build.gradle anymore and just define:

:app build.gradle

plugins {
    id("com.android.application")
    id("cz.ackee.gradle.plugin") version "1.5"
}

Actually not.

If there is implementation "com.android.tools.build:gradle:3.2.1" dependency in the plugin’s gradle.build and try to sync the main project I get following error:

Could not find com.android.tools.build:gradle:3.2.1.
Searched in the following locations:
  - https://plugins.gradle.org/m2/com/android/tools/build/gradle/3.2.1/gradle-3.2.1.pom
  - https://plugins.gradle.org/m2/com/android/tools/build/gradle/3.2.1/gradle-3.2.1.jar
Required by:
    project :app > cz.ackee.gradle.plugin:cz.ackee.gradle.plugin.gradle.plugin:1.6 > gradle.plugin.ackee-gradle-plugin:plugin:1.6
Add Google Maven repository and sync project
Open File
Enable embedded Maven repository and sync project

When I remove the dependency (and all code that refers to AppExtension) the project can sync as normal even with the plugin applied, but the plugin is almost useless then.


I feel like I am just one step away from finishing the plugin but I don’t know how to overcome this problem. It cannot find the dependency, because it is only searching in the Gradle’s repository. How can I force it to search for the plugin in other repositories as well? I have google() in every repositories {} block I have found, yet it doesn’t search for it there.

Any help will be greatly appreciated!

David