Gradle自定义插件(一)基础知识

Android advance

Posted by Kinsomy on October 25, 2019

1 概述

按照惯例,先放出Gradle Plugin的官方文档Using Gradle Plugins ,英文好的读者还是推荐阅读官方文档,更加准确详实。

都知道Gradle是在Android中用于项目自动化构建的工具,平时即使不自定义插件,也会用到官方或者三方库提供的很多插件。

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

那么自定义插件可以做什么呢?

一句话概括:按需定制构建流程

我们可以在项目构建过程中对构建流程进行干预,例如可以编写AOP插件进行字节码插桩操作埋点,也可以对资源文件做统一压缩。

2 实践

有三种方式可以自定义Gradle Plugin

  • 在build.gradle文件中直接编写
  • buildSrc 项目
  • 独立的java library

2.1 build.gradle中编写

这种方式是在项目的app.build文件中直接编写自定义插件,这样做的好处不需要做其他任何配置就会自动的被编译,但是因为写在项目内部,所以也不能独立出来被其他项目复用,这种方式很简单,使用的比较少。

apply plugin: HelloPlugin

class HelloPlugin implements Plugin<Project> {

    @Override
    void apply(Project target) {
        target.task("hello") {
            def extension = project.extensions.create("greeting", GreetingPluginExtension)
            doLast {
                println("${extension.message} from ${extension.greeter}")
            }
            println("-=-=-=-=-=-=-=-=Hello Plugin-=-=-=-=-=-=-=-=")
        }
    }
}

class GreetingPluginExtension {
    String message
    String greeter
}

greeting {
    message = 'Hi'
    greeter = 'Gradle'
}

在命令行执行./gradlew hello就可以看到输出的信息,doLast{}的作用就是会在task执行的最后去做的事情,extension是可以添加一些可配置的信息,代码很简单一目了然。

>./gradlew hello

> Configure project :HelloPlugin
-=-=-=-=-=-=-=-=Hello Plugin-=-=-=-=-=-=-=-=

> Task :HelloPlugin:hello
-=-=-=-=-=-=-=-=Hello Plugin last-=-=-=-=-=-=-=-=

2.2 buildSrc 项目

这种方式的代码集成在 rootProjectDir/buildSrc/src/main/java (或者rootProjectDir/buildSrc/src/main/groovy 、 rootProjectDir/buildSrc/src/main/kotlin)目录下,不再是直接在build.gradle文件中编写,但是写法和上述相同,好处是在本工程里,编写的插件对所有的build脚本都可见,但是依然不能打包复用到其他工程。

官方文档 Organizing Gradle Projects

首先在项目根目录下创建 buildSrc文件夹,注意这里的文件夹名必须是buildSrc

接着在buildSrc目录下创建build.gradle文件夹,并在里面配置如下代码,这里使用的是groovy编写,所以配置了groovy的plugin,也可以替换成java或者kotlin

//apply plugin: 'java-library'
apply plugin: 'groovy'
sourceSets {
    main{
        groovy{
            srcDir 'src/main/groovy'
        }
        resources {
            srcDir 'src/main/resources'
        }
    }
}

在buildSrc目录下创建src/main/groovy/<你的包名>/MyBuildSrcPlugin.groovy文件,编写以下代码

package com.learn.plugin;

import org.gradle.api.Plugin;
import org.gradle.api.Project;

class MyBuildSrcPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        project.task("MyBuildSrcPlugin") {
            println("-=-=-=-=-=-=-这是 MyBuildSrcPlugin=-=-=--=-=-=-=")
        }
    }
}

接着创建resources/META_INF/gradle-plugins/<包名>.properties 文件,在里面加一行配置

implementation-class=com.learn.plugin.MyBuildSrcPlugin

这样一个简单的buildSrc demo就出来了,编译一下,并在app的build.gradle中apply plugin: ‘com.learn.plugin’就可以使用,apply的名字就是包名。

2.3 独立的java library

这种方式以Android的module呈现,既然是module,显而易见的好处是插件被写出来可以发布,在其他项目中复用。

首先在项目里新建一个module,将module里除了build.gradle文件外全部删除,然后就可以按照2.2 buildSrc的方式进行编写项目结构,然后对build.gradle进行修改,将内容替换成下面的:

apply plugin: 'groovy'
apply plugin: 'maven'

dependencies {
    implementation gradleApi()
    implementation localGroovy()
}
repositories {
    mavenCentral()
}
repositories {
    mavenCentral()
}

uploadArchives {
    repositories {
        mavenDeployer {
            //设置插件的GAV参数
            pom.groupId = 'com.plugin'//你的包名
            pom.artifactId = 'myJarPlugin'
            pom.version = '1.1.9'//版本号
            //文件发布到下面目录  ../是父目录
            repository(url: uri('../repo'))
        }
    }
}

执行 gradlew :HelloPlugin:uploadArchives 就可以看到在项目根目录下生成了repo文件夹,里面有打包出来的jar文件。

然后在项目的build.gradle里面加入对jar包的依赖

buildscript {
    ...
    repositories {
        ...
        maven {//本地Maven仓库地址
            url uri('./repo')
        }
    }
    dependencies {
       ...
        classpath 'com.plugin:myJarPlugin:1.1.9'
    }
}

这样就可以在要用到的地方直接调用 apply plugin: ‘com.plugin’了。