如何从零开发一个 gradle 插件(二)

上一篇咱们介绍了 gradle 插件相关的概念,没看的同窗能够点击这里查看,这一篇让咱们结合例子来看看如何一步步建立一个 gradle 插件,并在 Android 项目中使用。java

IDE

工欲善其事必先利其器,要开发 gradle 插件得先决定用什么开发环境。我本身使用过 Intellij IDEA 和 AndroidStudio 来开发,由于 AndroidStudio 是基于 Intellij 改的,因此区别不是很大。android

但就我我的的偏好来讲更偏向于 Intellij,由于 AndroidStudio 是专门用来开发 Android 的,有不少配套的调试按钮,若是用来开发一个纯的 gradle 插件项目就会很别扭,因此个人判断原则是:api

  • 若是是一个纯的 gradle 插件项目,用 Intellij IDEA。
  • 若是是 Android 项目中内嵌的 gradle 插件项目,好比一个 module 用来放插件的代码,用 AndroidStudio。

语言

gradle 插件比较主流的开发语言是 groovy,由于 gradle 就是用 groovy 写的。经过查看第三方写的 gradle 插件代码发现大部分也是用 groovy 写的。bash

除了 groovy 还能够用来开发 gradle 插件的语言有:网络

  • java
  • kotlin
  • 其它基于 jvm 语言

由于 groovy 是基于 jvm 的,因此一样基于 jvm 的也能够用来写 gradle 插件。但 java 和 kotlin 是静态语言,意味着须要不停地判断类型和强转,相比之下,groovy 做为动态语言就没有这个问题。因此本文后续的插件代码都是 groovy 写的。app

具体开发以前让咱们先来看看要开发的 gradle 插件要知足什么需求。jvm

需求描述

实现一个插件,名字叫 io.helloworld.myplugin,须要实现下面的功能:maven

  • 进行 Android 自动配置
    • minSdkVersion 设置为 21
    • targetSdkVersion 设置为 26
    • compileSdkVersion 设置为 29
    • buildToolsVersion 设置为 ‘29.0.2’
  • 注册一个 Task,名字叫 myTask

具体步骤

  • 打开 Intellij IDEA,按 file -> new -> project 建立一个新项目。在 「new project」对话框左边选择 gradle,右边的 「Additional Libraries and Frameworks」只选择 Groovy:ide

  • 下一个界面选择表明你这个插件包的 groupId 和 ArtifactId,例如 io.helloworld.robotgradletools,版本号能够保持默认不变 1.0-SNAPSHOTpost

    groupId、artifactId 和 version 构成了咱们这个插件包的标识 Id,另外一个项目若是想使用咱们这个插件时,就须要经过这个 Id 来声明依赖。

  • 而后点 「next」-> 「finish」,项目结构大概像下面这样:

  • 由于要用到 gradle 的依赖,因此须要在项目 build.gradle 脚本文件中加一条 gradle 的依赖:

    dependencies {
        implementation gradleApi()
        ...
    }
    复制代码

    建立项目时,IDE 会默认添加上 groovy 的依赖:

    implementation 'org.codehaus.groovy:groovy-all:2.3.11'
    复制代码

    为了防止出现 groovy 版本不一致的问题,这里的依赖最好换成下面这样,让 gradle 自动去获取本地的 groovy 版本。

    implementation localGroovy()
    复制代码

    而后点一下 gradle 的同步按钮,保证 IDE 能引用到对应的类。

  • 在 groovy 文件夹下建立包 io.helloworld.robot,和前面设置的 groupId 保持一致。在这个包下建立一个 groovy 类 MyPlugin,代码以下:

    package io.helloworld.robot
    
    import org.gradle.api.Plugin
    import org.gradle.api.Project
    
    class MyPlugin implements Plugin<Project> {
        @Override
        void apply(Project project) {
            println("beginning of plugin 'MyPlugin'")
        }
    }
    复制代码

    能够看到 MyPlugin 实现了 Plugin<Project> 的接口,而这个接口有一个方法 apply(Project project),猜想当咱们这个插件在 build.gradle 中应用时,这个方法会被调用,咱们在这个方法中加上一行打印调试信息的代码。

    这里建立的插件是给 build.gradle 用的,因此 Plugin 的泛型类型是 Project,若是给 settings.gradle 用的话,泛型类型应该是 Settings

    如今咱们的插件已经建立好了(虽然很简陋),那怎样才能让 Android 项目使用到它呢?还须要再作两件事:建立插件的声明文件和将包含插件的软件包发布到 maven 仓库。

  • 建立插件的声明文件

    须要在 resources 文件夹下建立文件夹 META-INF/gradle-plugins,全部插件的声明文件都要放在这个目录下:

    插件的声明文件都是后缀为 properties 的配置文件,文件名就是插件的名字,例如这里的插件名字就是 io.helloworld.myplugin。在文件中经过 implementation-class 的值关联到上面建立的插件类 MyPlugin

    implementation-class=io.helloworld.robot.MyPlugin
    复制代码
  • 发布到 maven 仓库

    由于 maven 仓库不是这篇文章的重点,因此简单起见,这里将包含插件的软件包发布到本地仓库。

    要发布到本地仓库,build.gradle 须要加上下面这些代码:

    apply plugin: 'maven-publish'
    
    publishing {
        publications {
            mavenPub(MavenPublication) {
                // 这一行表示将 jar 包包含在要发布的组件中
                from components.java
                // 描述性信息
                pom {
                    name = 'Robot MyPlugin'
                    description = 'This is a test project for gradle plugin.'
                    url = 'http://www.helloworld.com'
                }
            }
        }
        repositories {
            maven {
                // 本地 repo 地址,这里写上大家电脑上本身的地址
                url = '/Users/zhanglei/projects/repo'
            }
        }
    }
    复制代码

    这里使用 maven-publish 插件来发布到 maven 仓库,其实发布到网络上也是相似的,将上面代码的 url 改为网络地址,再加上用户名/密码就能够了。

    改好 build.gradle 后点一下 gradle 的同步按钮,在 gradle 窗口的 Tasks 条目下就会看到 publishing 的 Task 分组,其中能够找到「publish」Task:

    双击执行这个 Task 来发布组件,执行结束后在上述本地仓库的地址下能够看到组件已经发布成功:

    OK,全部的准备工做都作完了,如今可使用插件了。

  • 在 Android 项目中使用插件

    由于咱们的插件是配置 Android 相关信息,因此要在 application 类型的 module 下使用。在 AndroidStudio 中打开 module 下的 build.gradle 文件,加上下面的代码:

    // 使用插件
    apply plugin: 'io.helloworld.myplugin'
    buildscript {
        repositories {
            // 声明本地 repo 的地址
            maven {
                url '/Users/zhanglei/projects/repo'
            }
        }
        dependencies {
            // 声明依赖咱们上面发布到本地 maven 仓库的软件包
            classpath 'io.helloworld.robot:gradletools:1.0-SNAPSHOT'
        }
    }
    复制代码

    由于插件发布在本地仓库中,因此要在 buildscript.repositories 中声明一下仓库地址。而后在 AndroidStudio 中同步下 gradle 就能够看到咱们刚才写在 apply() 中的调试代码输出的 log:

    AndroidStudio 中同步 gradle 和 Intellij 中稍微有点不同:点下面这个按钮:

    好的,咱们如今把开发插件到使用插件这条路调通了,接下来咱们在插件中完成上面说的「插件需求」,先来看看第一个:

  • 实现插件功能一:进行 Android 自动配置

    • minSdkVersion 设置为 21
    • targetSdkVersion 设置为 26
    • compileSdkVersion 设置为 29
    • buildToolsVersion 设置为 29.0.2

    在 Intellij 中打开 MyPlugin 类,在 apply() 方法中加上下面这段代码:

    project.extensions.findByName('android').with {
        getProperty('defaultConfig').with {
            setProperty('minSdkVersion', 21)
            setProperty('targetSdkVersion', 26)
        }
        setProperty('compileSdkVersion', 29)
        setProperty('buildToolsVersion', '29.0.2')
    }
    复制代码

    而后发布到本地仓库,而后在 AndroidStudio 中同步下 gradle,这就至关于在 build.gradle 中写了:

    android {
        defaultConfig {
            minSdkVersion 21
            targetSdkVersion 26
        }
        compileSdkVersion 29
        buildToolsVersion '29.0.2'
    }
    复制代码

    第一个需求完成了,接下来看一下第二个需求。

  • 实现插件功能二:注册一个 Task myTask

    打开 MyPlugin,在 apply() 方法中加上下面这段代码:

    project.task('myTask') {
        group 'helloworld'
        description 'This is a task named myTask, created in myPlugin'
        doFirst {
            println("run in myTask it $it")
        }
    }
    复制代码

    这里建立了一个名叫 myTask 的 Task,并设置了 group、description 和它的运行代码。和上面同样,将插件发布到本地仓库,并同步 Android 项目的 gradle。能够看到 Android 项目中已经存在 myTask Task:

到这里一个拥有基本功能的 gradle 插件就开发好了,若是想继续扩展这个插件的功能,就继续在 apply() 方法里添加代码。由于 apply() 方法的参数是 project,因此这里能够实现 build.gradle 中的全部能力。你也能够在这个项目中开发一个新的插件,放一些特殊的 gradle 处理逻辑。

关于 gradle 插件开发就简单介绍到这里,因为我也是边开发边学习,不免有一些不对的地方,欢迎你们评论指正。

相关文章
相关标签/搜索