android Gradle插件分类与使用

  • 简介
  • 作用与优点
  • 作用
  • 优点
  • 插件分类
  • 脚本插件
  • 对象插件
  • 内部插件
  • 第三方插件
  • 对象插件自定义
  • 插件DSL
  • Android Gradle 插件
  • 分类
  • 编写与集成
  • 编写
  • build.gradle中编写
  • buildSrc编写
  • 独立项目编写
  • 集成
  • 插件的生成
  • 本地的集成
  • 小结


简介

Gradle 是一款非常优秀的构建系统工具,它的DSL基于Groovy实现,可以通过DSL来达到你构建的目的。其中提供了插件的概念,基于Gradle进行很好的扩展,而不改变其核心基础,又能满足不同业务的需要。
这里只说android gradle 插件
从Gradle的角度来说,Android其实就是Gradle的一个第三方插件,由Google开发的。但从Android角度来看,Android插件是基于Gradle构建的,然后加上Gradle Wapper(包装器,保证对于studio运行时,gradle的环境和版本带来一个确定性,并且能快速启动gradle)和studio完美搭建了android构建系统。

作用与优点

作用

  • 为项目配置依赖
  • 为项目配置约定,比如约定代码的存放位置、签名位置
  • 为项目添加任务,比如测试、编译、打包等
  • 为项目的核心对象和其他插件的对象添加扩展类型
  • 为项目提供公共化配置

优点

  • 更高程度的模块化
  • 重用和减少维护在多个项目类似的逻辑开销
  • 封装必要的逻辑,并允许构建脚本尽可能是声明性的

插件分类

脚本插件

先看代码,根目录定义config.gradle文件:

ext {
    cfgs = [
            compileSdkVersion : 29
    ]
    android = [

            versionName : '1.0.0'
    ]
}

在根gradle文件中引入插件

apply from: "config.gradle"

task test{
    doLast{
        println("版本名称是:${android.versionName}")
    }
}

执行 ./gradlew test,会输出:版本名称是:1.0.0

实际上这不算真正的脚本插件,但定义还是脚本插件。更像是c++的头文件引入。
应用脚本插件,其实就是把这个脚本加载进来,使用apply from关键字引入的。但是作用也很大,我们在多模块开发的时候,我们可以庞大的脚本文件,进行分块、分段整理,拆分成一个个公用、职责分明的文件。比如:将很多共有的库版本号一起管理、应用构建版本一起管理、maven配置脚本文件抽取等等。

对象插件

对象插件(二进制插件)是实现了org.gradle.api.Plugin接口的插件。可以分为内部插件和第三方插件。

内部插件

内部插件是gradle提供的,它们可以有plugin id。
比如我们定义一个Java插件

apply plugin : org.gradle.api.plugins.JavaPlugin

由于Gradle会帮我们默认导入org.gradle.api.plugins包,所以可以省略前缀,如下:

apply plugin :JavaPlugin

更简洁的,对于Gradle自带的核心插件都有一个容易记的短名,称其为plugin id,比如这里的Java插件对应的id就是java,所以简化如下:

apply plugin :'java'

第三方插件

第三方的对象插件通常是jar文件,要想让构建脚本知道第三方插件的存在,需要使用buildscrip来设置依赖,需要配置classpath。
我们最熟悉的android Gradle插件也属于第三方插件,我们经常会这么写:

buildscript {
    ext.kotlin_version = '1.3.10'

    repositories {
       jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        
    }
}

然后我们才能引入apply plugin: 'com.android.application'

对象插件自定义

写一个简单的自定义插件,按照标准要实现Plugin接口:

class GreetingPlugin implements Plugin<Project>{

    /**
     * Apply this plugin to the given target object.
     *
     * @param target The target object
     */
    @Override
    void apply(Project target) {
        target.task('testplugin'){
            doLast {
                println('hello the GreetingPlugin')
            }
        }
    }
}
apply plugin: GreetingPlugin

当插件应用于项目时,Gradle将创建插件类的实例,并调用实例的apply方法。这里我们定义了一个task任务,然后在控制台执行这个任务:

./gradlew testplugin

会输出:

> Task :testplugin
hello the GreetingPlugin

插件DSL

plugins DSL是一种新出的插件应用放肆,需要在Gradle 2.1 以上版本才可以使用。
插件DSL正在孵化(incubating)中,请注意,在以后的Gradle版本中,DSL和其它配置可能会改变。
使用就是依靠闭包代码来设置插件,比如指定Java插件:

plugins {
    id 'java'
}

还有就是如果该插件已经被托管在https://plugins.gradle.org/上,就不需要配置classpath依赖了,直接使用plugins就可以使用插件:国内网差

plugins{
	id "org.sonarqube" version "1.2"
}

Android Gradle 插件

分类

可根据工程类型分成一下:

  • 应用程序插件:它可以生成一个可运行的apk应用,插件id为:com.android.application。
  • 库插件:它可以生成AAR包给其他的APP工程公用,跟Jar一样,但是塔包含了Android资源等信息,插件id为:com.android.library。
  • 测试插件:用于对其他模块进行测试,插件id为:con.android.test。
  • feature插件:用于创建Android Instant App 是需要用到,插件id为:com.android.feature。
  • Instant App插件:是Android Instant App 的入口,插件id为:com.android.instantapp.

编写与集成

编写

对于插件的编写,可以使用java、kotlin、groovy语言,都是基于虚拟机。这里选groovy语言编写

build.gradle中编写

第一种:就跟前面写的自定义对象插件一样,直接写在项目build.gradle里面,这种一般不推荐,很low。

buildSrc编写

第二种: 在buildSrc下编写插件。根目录下创建buildSrc目录(或者通过创建java 模块也行),请仔细检查名字是不是对的,buildSrc是Android studio预留的命名,它会自动识别并构建的。在分别创建以下文件或目录:
build.gradle 需要引入groovy的sdk,也可以指定sourceSets的目录:

//我们使用groovy来编写,引入groovy库
apply plugin: 'groovy'
//apply plugin: 'java-library'

创建src/main/groovy目录(如果java编写,请放在java目录)

AS gradle插件对应gradle版本 Java版本 gradle android插件_Gradle


其中recources目录是用来配置资源的,如果需要在引入包名,可以在groovy里面创建包名,之后需要在该目录下指定。在resources目录下创建目录META-INF/gradle-plugins目录,最后在该目录下编写插件属性文件com.hujin.plugin.properties文件。其com.hujin.plugin就是定义的包名路径,而.properties是后缀,千万别写错了。然后在该文件中编写插件的全类名:implementation-class=com.hujin.plugin.MyTestPlugin

我们这里简单引入单个文件为例子,不处理包名。后面会以包名方式再介绍

创建一个文件,跟上面的自定义一样,实现Plugin接口的类,切记,文件一定要以.groovy结尾,要不然就会找不到。重点:.groovy结尾

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

class MyTestPlugin implements Plugin<Project>{

    @Override
    void apply(Project project) {
        println('MyTestPlugin is Run')
    }
}

写完之后记得同步下或者rebuild下。
在主项目的build.gradle下引入:

//包名类型的,请引入包名的字符串
apply plugin: MyTestPlugin

执行build输入完成,输出:

MyTestPlugin is Run

小问题:我遇到一个报错,但是不影响使用:

AS gradle插件对应gradle版本 Java版本 gradle android插件_maven_02


删掉buildSrc/build/libs/buildSrc.jar包,就正常了。这个jar包属于编译产物,是可以分享的。看下种方案会介绍,或者不创建resources目录,并删掉所以build目录再同步就好了。

独立项目编写

第三种:这种方案可以发布在本地或者远程仓库,给其他人使用。另其一个工程,这里使用idea创建一个groovy工程。

AS gradle插件对应gradle版本 Java版本 gradle android插件_android_03


然后修改build.gradle配置如下:

plugins {
    id 'groovy'
}

group 'com.share.plugin'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    compile gradleApi()
    compile localGroovy()
    compile 'org.codehaus.groovy:groovy-all:2.3.11'
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

然后跟buildSrc操作一样,在src/main/groovy目录下创建一个包,比如创建com.hujin.plugin包,下创建ShareCustomPlugin插件。

AS gradle插件对应gradle版本 Java版本 gradle android插件_maven_04


然后需要提供一个属性文件来配置插件的位置,就是要插件properties文件,在resources目录下,再创建一个META-INF/gradle-plugins/目录,再创建属性文件com.hujin.plugin.properties,写入代码:

//  src/main/resources/META-INF/gradle-plugins/com.hujin.plugin.properties
implementation-class=com.hujin.plugin.ShareCustomPlugin

implementation-class属性为自定义插件的属性。编写完毕了。

集成

插件的生成

集成还是使用本地maven模式。远端参考android mac搭建Nexus3.+私有maven这个操作。
修改原build.gradle文件:引入maven库。
注意目录,有的创建项目多进或少进了一层目录../repositoryrepository

plugins {
    id 'groovy'
}
//引入maven库
apply plugin: 'maven'

repositories {
    mavenCentral()
}

def group = 'com.hujin.plugin'
def version = '1.0.0'
def artifactId = 'myGradlePlugin'
uploadArchives{
    repositories.mavenDeployer{
        // 配置本地仓库路径,项目根目录下的repository目录中
        repository(url: uri('repository'))
        pom.groupId = group
        pom.artifactId = artifactId // 项目名称(通常为类库模块名称,也可以任意)
        pom.version = version
    }
}

dependencies {
    compile gradleApi()
    compile localGroovy()
}

同步后,找到右侧Gradle侧边栏:执行uploadArchives

AS gradle插件对应gradle版本 Java版本 gradle android插件_maven_05


然后会生成本地maven文件:

AS gradle插件对应gradle版本 Java版本 gradle android插件_gradle_06


而图中的myGradlePlugin-1.0.0.jar包就是我们需要的插件jar包。

远端配置完后,会到本地android项目

本地的集成

本地项目还是以android为例子,参考tools.build:gradle的引入。

  1. 在根build.gradle中,引入本地maven仓库:
buildscript {
    repositories {
        google()
        jcenter()
        maven {
        //这个url 是 上个项目,生成的本地maven文件,你也可以copy到本地,一样的
            url 'file:/Users/apppp/IdeaProjects/CustomPluginShare/repository'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.4'
        classpath 'com.hujin.plugin:myGradlePlugin:1.0.0'
    }
}

repository这个是插件项目下地址。

  1. 引入classpath:
classpath 'com.hujin.plugin:myGradlePlugin:1.0.0'

3.导入插件

apply plugin: 'com.hujin.plugin'

验证是否引入成功,执行 task 'assembleDebug',会打印出ShareCustomPlugin的打印代码:

> Configure project :
第三方插件 ShareCustomPlugin  被调用

小结

这里还是简单的创建和使用,还没有真正的项目化。如何写一个插件,能帮助项目自动化或者便捷化,才是真正的开始。