Android studio通过Gradle来构建我们的项目。一般情况下,我们只是使用Gradle来配置一些功能,比如,buildTypes,productFlavors等等。
实际上,Gradle提供了很多有用的功能,可以让我们更加方便的管理我们的项目。

这篇,我们介绍下Gradle的Plugin插件。
官方介绍

Gradle的plugin插件,有三种方式:

  • 一,Build script 简单说就是在构建脚本中(build.gradle),直接创建编写代码
  • 二,buildSrc project 创建一个buildSrc的项目,存放插件的代码
  • 三,Standalone project 创建一个单独的项目,生成并发布一个包含插件,任务等内容的jar包。

下面,我们就介绍下三种方式的插件分别怎么创建。

一,Build script

这种方式,就是直接在build.gradle文件中,编写插件代码。

好处:
自动编译,无需执行其他操作。

坏处:
生成的插件,对外部是不可见的,只能在当前的功能下使用。

一般来说,不会使用这种方式。

先看下插件的编写

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.task('hello') {
            doLast {
                println 'Hello from the GreetingPlugin'
            }
        }
    }
}

// Apply the plugin
apply plugin: GreetingPlugin

一般来说,我们写的插件,都需要实现Plugin接口。在apply()方法中,写我们要实现的插件代码。

通过 gradlew -q hello调用。

D:\workspace\work_studio\ObjectAnimatorTest>gradlew -q hello
Hello from the GreetingPlugin
D:\workspace\work_studio\ObjectAnimatorTest>

这样,就打印出来结果了。

二,buildSrc project

这种方式,就是创建一个buildSrc的module。
因为,Gradle插件支持groovy,java,kotlin语言,所以,根据我们使用的语言,可以把插件代码分别放到下面几个不同的目录下
rootProjectDir/buildSrc/src/main/groovy
或rootProjectDir/buildSrc/src/main/java
或rootProjectDir/buildSrc/src/main/kotlin

比如,我们想使用java语言来开发插件代码,我们就需要把我们的java代码放到rootProjectDir/buildSrc/src/main/java这个目录下。

这种方式实现的插件好处:
所有的构建脚本都是可见的。

坏处:
只有当前的工程才能使用,其他的工程是不能使用的

下面,我们就开始实现插件代码。

2.1 创建buildSrc的module。

创建一个名字为 buildSrc(名字必须是这个) 的Android module。

把里面的build文件夹,src下面的res文件夹等等,全部删除。

目录结构如下

用java 自定义grafana 插件 自定义gradle插件_用java 自定义grafana 插件

2.2 通过build.gradle添加依赖

上面说了,我们可以使用groovy,kotlin,java等语言开发。一般来说,使用Java或Kotlin实现的插件是静态类型的,其性能将优于使用Groovy实现的相同插件。这里,我们就使用最熟悉的Java来开发。

给buildSrc的module的build.gradle中添加依赖

//use java library
apply plugin: 'java-library'
//groovy library
//apply plugin: 'groovy'
apply plugin: 'maven'



dependencies{
    // gradle sdk
    compile gradleApi()
    // groovy sdk
    compile localGroovy()
}

repositories{
    google()
    mavenCentral()
}
2.3 创建插件代码

创建插件,需要实现Plugin接口。

这里,我们打印一句话。毕竟,我们只是学习创建Plugin插件的。

package com.liu.loadplugin;

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

public class UploadPlugin implements Plugin<Project> {

  @Override
  public void apply(Project project) {
    System.out.println("this is my first buildSrc plugin !");
  }
}
2.4 创建properties文件,关联插件

我们创建好了插件,接下来,我们需要创建一个properties的文件,把插件的名字跟插件关联起来。

1,创建目录及文件 main/META-INF/gradle-plugins/插件名.properties文件。

比如,我们现在的插件名字是com.liu.loadplugin.properties。

如下图

用java 自定义grafana 插件 自定义gradle插件_plugin_02

2,在properties文件添加代码,关联插件

implementation-class=com.liu.loadplugin.UploadPlugin

这个就是关联插件类的全路径(点击是可以跳转到类里面的)。

到这里,我们整个的buildSrc类型的插件就开发完了。

2.5 使用插件

在我们的app的module的build.gradle里面引用插件。

apply plugin: 'com.liu.loadplugin'

这里的名字是跟我们的properties的名字对应的。

重新构建一次,会看到我们在插件里写的那句话,打印出来了。

用java 自定义grafana 插件 自定义gradle插件_plugin_03

到这里,我们buildSrc方式开发插件就完成了,下面看下独立的插件开发方式。

三,Standalone project

独立的插件。跟buildSrc的创建方式类似。
但是,它相比与上面的那种,有几个明显的优点:

  • 插件的module名字,可以随意
  • 这种方式,就是将我们写的一些插件,任务等等打包到一起,生成jar,通过jar包的方式使用。所以, 在其他的项目也是可以使用的

下面,我们来创建一个独立的插件。

3.1 创建一个插件的module

跟上面的方式类似,我们创建一个叫alone_plugin(名字随意)的Android module。然后,删除build,res等无用的文件。

结构如下。

用java 自定义grafana 插件 自定义gradle插件_插件_04

3.2 添加依赖(build.gradle)

因为,这种独立插件的方式,最后是通过生成jar包,来共其他工程使用。所以,这里跟上面的方式有点不同。
先看下,build.gradle文件

apply plugin: 'java-library'
apply plugin: 'maven'
dependencies {
    compile gradleApi()
    compile localGroovy()
}
repositories {
    mavenCentral()

}

group = 'com.liu.alone.plugin'
version = '1.0.0'
archivesBaseName = 'java-plugin'

//upload
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri('../repo'))
        }
    }
}

这里比buildSrc的方式多了下面,这些配置

group = 'com.liu.alone.plugin'
version = '1.0.0'
archivesBaseName = 'java-plugin'

//upload
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri('../repo'))
        }
    }
}

我们是通过maven的方式,把插件发布到本地的repo目录下。我们知道maven发布需要指定:groupId,artifactId,version的。通过,这三个声明,就可以找到我们的插件。

3.2 创建插件,跟properties文件

这两个步骤跟我们上面的buildSrc创建插件的方式一样。这里就不写了。

目录结构如下图

用java 自定义grafana 插件 自定义gradle插件_android_05

3.3 maven发布插件

通过Gradle的alone_plugin下面的uploadArchives命令。
把我们的插件,发布到当前工程的repo目录下。

用java 自定义grafana 插件 自定义gradle插件_plugin_06

通过上面的命令,就会把插件发布到项目下的repo目录里面。

如下图

用java 自定义grafana 插件 自定义gradle插件_用java 自定义grafana 插件_07

3.4 引入插件

在项目的build.gradle引入我们发布的插件

buildscript {
    repositories {
        google()
        jcenter()
        maven{
            url uri('./repo/')
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.1'

        classpath 'com.liu.alone.plugin:java-plugin:1.0.0'
    }
}

通过添加maven仓库。在dependenies里面引用。就把我们的插件引入了。

3.5 使用

在app module的build.gradle里面引用跟buildSrc的方式一样。

apply plugin: 'com.liu.alone.plugin'

最后,重新构建一次。就会打印出,我们插件里写的Log。

用java 自定义grafana 插件 自定义gradle插件_android_08

到这里,自定义Gradle 插件的三种方式,就介绍完了。

独立的插件,我们这里只是说了,在打包的项目使用。那么,其他的项目应该怎么使用呢。

3.6 其他项目引用插件及优化
3.6.1 其他项目引入插件

独立的插件开发方式的最终目的是让其他的项目也可以使用。那么,别的项目,怎么来引用呢。

这里,我们让其他的项目通过jar包的方式来引用。

首先,在需要引入的项目,创建一个libs文件夹(这个应该是可以随意起的)。

用java 自定义grafana 插件 自定义gradle插件_用java 自定义grafana 插件_09

其次,修改项目的build.grandle

buildscript {
    repositories {
        google()
        jcenter()
        flatDir{dir 'libs'}
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.1'

        classpath 'com.liu.alone.plugin:java-plugin:1.0.0'
    }
}

这里,我们需要把libs添加进仓库中,然后,依赖这个插件。就完成了在其他项目的使用。

我们再来想一下。这种方式,是需要我们手动把jar包拷贝到需要的项目中的。有什么问题呢?

  • 1,手动拷贝,没有那么自动化
  • 2,如果这个插件升级了或者修改了呢,我们每次都拷贝?

既然是多个项目用的话。那么,我们可不可以上传到本地仓库。然后,其他的项目也使用本地仓库,来解决上面的问题呢。

3.6.2 优化,上传到本地仓库

这里关于本地仓库配置本地Maven库,就不说明了。

我们首先创建一个本地仓库。让其依赖一个组(android_depend)。
因为我们不只是有一个插件,还有jcenter等等,都可以放到本地仓库中。

用java 自定义grafana 插件 自定义gradle插件_用java 自定义grafana 插件_10


然后,修改我们的独立插件alone_plugin的build.gradle。使其发布到本地仓库的android_plugin中,而不再发布到项目的repo目录下。

apply plugin: 'java-library'
apply plugin: 'maven'
dependencies {
    compile gradleApi()
    compile localGroovy()
    compile 'com.android.tools.build:gradle:3.3.1'
    implementation("com.squareup.okhttp3:okhttp:3.8.1")
}
repositories {
    mavenCentral()

}

//group = 'com.liu.alone.plugin'
//version = '1.0.0'
//archivesBaseName = 'java-plugin'
//
//upload
//uploadArchives {
//    repositories {
//        mavenDeployer {
//            repository(url: uri('../repo'))
//        }
//    }
//}

//upload to local maven

uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: "http://localhost:8081/artifactory/android_plugin/") {
                authentication(userName: "admin", password: "admin")
            }
            pom.version = "1.0.0"
            pom.artifactId = "java-plugin"
            pom.groupId = "com.liu.alone.plugin"
        }
    }
}

这里,我们已经修改其发布的位置了。发布成功后,看下本地仓库。

用java 自定义grafana 插件 自定义gradle插件_gradle_11


这里,我们看到已经发布上去了。

然后,我们修改要引用插件的项目下的build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
//        google()
//        jcenter()
        maven{
            url 'http://localhost:8081/artifactory/android_depend/'
        }
//        flatDir{dir 'libs'}
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.1'

        classpath 'com.liu.alone.plugin:java-plugin:1.0.0'
    }
}

allprojects {
    repositories {
//        google()
//        jcenter()
        maven{
            url 'http://localhost:8081/artifactory/android_depend/'
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

疑惑:这里需要,先发布到本地仓库;然后,把本地仓库添加到组中,这样,组中才有插件的包。
先把本地仓库添加到组中,在发布插件到本地仓库,这样组中是没有这个插件包的(本地仓库有)。

这里,我们看到,我们已经不再使用 libs 目录了,而是换成了本地仓库。
这样的话,如果,独立插件再发布修改或者升级的话,我们也不需要手动拷贝jar包了。直接修改版本就可以了。

到这里,Gradle的插件开发,就全部介绍完了。



自定义插件非常实用,我们完全可以通过自定义插件来一键实现打包,加固,上传,钉钉通知等功能。