Android Gradle 插件开发入门指南(一)

16,269 阅读6分钟

gradle-org-hero@2x.png
Android Gradle 插件开发入门指南一共规划了三篇文档:

一、Gradle 插件是什么?

Gradle 全称 Gradle Build Tool(构建工具),可以使用它构建任何你想构建的东西,Gradle 拥有丰富的 API 和成熟的插件和集成系统,我们能够很方便的介入构建过程和定制构建产物。扩展 Gradle 原有功能的常见手段就是自定义 Gradle Plugin,Gradle 插件简单概括就是将构建逻辑的可重用部分打包起来,应用到不同的项目和构建中。

二、如何自定义 Gradle Plugin

参考文档地址:docs.gradle.org/current/use…
自定义 Gradle 插件有三种方式:

  • 构建脚本

可以直接在构建脚本中包含插件的源代码。这样做的好处是插件可以自动编译并包含在构建脚本的类路径中,而不需要您做任何事情。然而,插件只能在定义它的构建脚本之内可见,不能在其他脚本中复用插件。

  • buildSrc

可以将插件的源代码放在rootProjectDir/buildSrc/src/main/java目录(或rootProjectDir/buildSrc/src/main/groovyrootProjectDir/buildSrc/src/main/kotlin中,具体取决于你使用的语言)。 Gradle将负责编译插件,并使其在构建脚本的类路径中可用。 该插件对整个项目里的每个构建脚本都是可见的, 但是,它在项目外部不可见,因此不能其他项目中复用该插件。

  • 独立项目

可以为插件创建一个单独的项目,将项目打包成一个JAR包,然后可以在多个项目中复用。

三种方式,由简到难,插件的实现逻辑是完全一致的,区别在于插件的打包方式。掌握第三种,前面两种就是水到渠成的事情了,所以下面以第三种方式为例,详细讲解Gradle插件的开发过程。

三、创建 Gradle Plugin Project

参考文档:docs.gradle.org/current/use…
Gradle 作为成熟的构建工具,已经为我们准备好了相关的插件,Gradle Plugin Development Plugin,Gradle 插件开发插件,有点拗口,但是表述很准确,就是专门服务于插件开发的插件,使用起来也是很方便的。

  • 手动创建插件工程
    • 首先创建一个文件夹作为我们插件工程的存放目录,如 HelloPlugin
    • 在目录下新建一个 build.gradle 文件,这就是我们的编译脚本
    • 在 build.grale 脚本中应用 Gradle Plugin Development Plugin,并声明插件信息
// 和 Android 开发中的 apply plugin 等效
plugins {
    id 'java-gradle-plugin'
}

gradlePlugin {
    plugins {
        // 声明插件信息,这里的 hello 名字随意
        hello {
            // 插件ID
            id = 'com.lenebf.plugin.hello'
            // 插件的实现类
            implementationClass = 'com.lenebf.plugin.HelloPlugin'
        }
    }
}
  • 接下来和普通的 Java 项目一样需要创建一个相对路径为 src/main/groovy/com.lenebf.plugin 的文件夹,里面存放我们的插件实现类HelloPlugin.groovy,然后就可以在HelloPlugin.groovy里面实现插件的具体功能了。

看起来有点复杂,有没有更加简便的方式呢?有!

  • 自动创建插件工程
# 在HelloPlugin目录下,使用 gradle init 命令创建构建
$ gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
  
# 🤤😍🤩 我们要的东西出现了,选4 Gradle 插件
Enter selection (default: basic) [1..4] 4

Select implementation language:
# 实现语言我们选择 Groovy,你可以选择你自己熟悉的语言
  1: Groovy
  2: Java
  3: Kotlin
Enter selection (default: Java) [1..3] 1

# DSL(Domain-specific language 特定领域语言),也就是我们编译脚本语言,我们同样选 Groovy
Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Project name (default: hello):
Source package (default: hello): com.lenebf.plugin

不要被上面出现多次的 Groovy 吓到,我们不需要特别熟悉它,对着文档能使用它即可。

四、Hello World

前面插件工程已经创建好了,现在我们实现一个简单的插件了,这个插件的作用是向应用该插件的项目注册一个名为 greeting 的任务,这个任务需要做的事情就是在 doLast 的时候打印一句话,就这么简单。

/**
 * A simple 'hello world' plugin.
 */
public class HelloPlugin implements Plugin<Project> {
    public void apply(Project project) {
        // Register a task
        project.tasks.register("greeting") {
            doLast {
                println("Hello from plugin 'com.lenebf.plugin.hello.greeting'")
            }
        }
    }
}

五、发布插件

要使用插件,我们得先把插件打包成jar文件,这个就叫做发布 Publish,然后才能在其他项目里引入插件。发布插件我们需要借助Maven Publish Plugin,首先在前面的build.gradle中应用该插件:

// 和 Android 开发中的 apply plugin 等效
plugins {
    ...
    id 'maven-publish'
}

然后需要定义插件的发布信息:

publishing {
    publications {
        // 这里的 hello 可以任意命名
        hello(MavenPublication) {
            // 插件的组ID,建议设置为插件的包名
            groupId = 'com.lenebf.plugin'
            // 翻译过来是 工件ID,我的理解是插件的名字
            artifactId = 'hello'
            version = '0.0.1'
            // 组件类型,我们的插件其实就是Java组件
            from components.java
        }
    }
}

插件的发布信息定义好之后,我们还需要告诉Maven Publish Plugin插件往哪发布:

  • MavenLocal(Maven本地仓库)

发布插件和构建Android程序一样,执行一个Gradle Task。通过上面的配置我们已经能够将插件发布到Maven的本地仓库了,我们可以通过./gradlew tasks命令或者直接在Idea里查看哪个任务对应着插件发布,截图里高亮的就是了:
image.pngimage.png
成功执行该任务,在Maven的本地仓库就能看到插件了,本地仓库地址/Users/[用户名]/.m2/repository
image.png

  • 自定义发布地址

如果不想使用MavenLocal,我们也可以自定义插件发布地址

publishing {
    ...
    repositories {
        maven {
            // $rootDir 表示你项目的根目录
            url = "$rootDir/repo"
        }
    }
}

配置完自定义发布地址后,我们的任务里会出现一个名为PublicationToMavenRepository的任务,成功执行该任务,我们的插件就会打包并发布到指定的地址了
image.png

六、测试插件功能

插件已经开发并发布完成,现在需要创建一个Android项目并在项目中应用该插件,测试插件功能是否正常。

改造插件 Project

现在我们的插件Project和 Android Project是相互独立的,后续调试插件时需要来回的切换两个Project,不是很方便,我们先来改造下插件 Project,让它作为一个Module存在于Android Project中,这样调试起来就方便多了。

1. 复制插件目录,删除无用文件以及文件夹

将插件 Project的完整文件夹复制到到Android Project的根目录里,删除插件目录下的以下文件和目录

  • gradle文件夹,gradle包装文件存放目录,Module不需要
  • gradlew,Gradle在Linux/macOs平台可执行脚本,Module不需要
  • gradlew.bat,Gradle在Window平台可执行脚本,Module不需要
  • settings.gradle,Project的配置脚本,Module不需要
  • .gradle文件夹,gradle的版本配置信息,Root Project才需要,作为Module已经不需要了
  • .idea文件夹,IDEA的工程配置信息,作为Module已经不需要了
  • repo文件夹,前面生成的插件包存放目录,后续会重新生成并且为之会发生变化,也不需要了

image.png

2. 修改插件Project为Module

修改Android Project根目录下的settings.gradle,使其包含插件目录,这样我们的插件 Project就变成一个Module了
image.png

3. 统一插件应用方式

不同的Gradle版本,插件的应用方式不同,有apply plugin: 'xxx'plugins { id 'xxx'}两种,修改插件的build.gradle,使其和app构建脚本的应用方式保持一致
image.png
image.png

4. 同步Gradle修改

点击Gradle同步按钮,同步成功后插件Project就变成Android Project的一个Module了。执行上述的插件发布任务,就能在工程根目录下的repo文件夹看到我们的插件包了
image.pngimage.png

应用并测试插件

要让Android Project可以正常使用插件,首先得告诉它插件在哪?叫什么名字?是用哪个版本的插件?
image.png
那为什么前面使用Gradle Plugin Development PluginMaven Publish Plugin时不需要指定这些信息呢?这两个插件已经包含在Gradle的核心库里了,核心库里的插件直接使用就好了。
然后需要对我们的app应用插件
image.png
然后image.png同步下工程,在任务列表里就能看到我们的greeting任务了
image.png
执行下greeting任务,看看结果是否如我们所愿
image.png Nice Job!

七、结束

文档中示例代码:github.com/lenebf/Grad…
根据上面一步一步的操作,我们成功的编写、发布并测试了插件,是不是很简单,和一个简单的Java项目非常相似有没有!
这篇文档看起来可能会觉得比较啰嗦,主要是想尽量详细描述整个过程,让大家照着做肯定有一个正确的结果;另外文字描述中英文混合,读起来可能也比较拗口,其实是想比较准确的表达自己的意思,比如Project和Module没办法找到一个合适的中文单词代替,但是如果是做Android开发的,一看英文描述就知道什么意思,换成中文反而不好理解了。