欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Gradle自定义插件

程序员文章站 2022-07-12 10:27:51
...

Android Gradle

Android项目使用 Gradle 作为构建框架,Gradle 又是以Groovy为脚本语言。所以学习Gradle之前需要先熟悉Groovy脚本语言。

Groovy是基于Java语言的脚本语言,所以它的语法和Java非常相似,但是具有比java更好的灵活性。

Android Gradle 的 Project 和 Tasks

这个是Gradle中最重要的两个概念。每次构建(build)至少由一个project构成,一个project 由一到多个task构成。项目结构中的每个build.gradle文件代表一个project,在这编译脚本文件中可以定义一系列的task;task 本质上又是由一组被顺序执行的Action`对象构成,Action其实是一段代码块,类似于Java中的方法。

  • Android Gradle 构建生命周期

每次构建的执行本质上执行一系列的Task。某些Task可能依赖其他Task。那些没有依赖的Task总会被最先执行,而且每个Task只会被执行一遍。每次构建的依赖关系是在构建的配置阶段确定的。每次构建分为3个阶段:

  • Initialization: 初始化阶段

这是创建Project阶段,构建工具根据每个build.gradle文件创建出一个Project实例。初始化阶段会执行项目根目录下的settings.gradle文件,来分析哪些项目参与构建。

所以这个文件里面的内容经常是:

 include ':app'
 include ':libraries'

这是告诉Gradle这些项目需要编译,所以我们引入一些开源的项目的时候,需要在这里填上对应的项目名称,来告诉Gradle这些项目需要参与构建。

  • Configuration:配置阶段

这个阶段,通过执行构建脚本来为每个project创建并配置Task。配置阶段会去加载所有参与构建的项目的build.gradle文件,会将每个build.gradle文件实例化为一个Gradle的project对象。然后分析project 之间的依赖关系,下载依赖文件,分析project下的task之间的依赖关系。

  • Execution:执行阶段

这是Task真正被执行的阶段,Gradle会根据依赖关系决定哪些Task需要被执行,以及执行的先后顺序。

task是Gradle中的最小执行单元,我们所有的构建,编译,打包,debug,test等都是执行了某一个task,一个project可以有多个task,task之间可以互相依赖。例如我有两个task,taskA和taskB,指定taskA依赖taskB,然后执行taskA,这时会先去执行taskB,taskB执行完毕后在执行taskA。

你点击AndroidStudio右侧的一个Gradle按钮,会打开一个面板,内容差不多是这样的:
Gradle自定义插件
里面的每一个条目都是一个task,那这些task是哪来的呢?

一个是根目录下的 build.gradle 中的:

dependencies {
   classpath 'com.android.tools.build:gradle:3.2.1'
}

一个是 app 目录下的 build.gradle 中的:

apply plugin: 'com.android.application'

这两段代码决定的。也就是说,Gradle提供了一个框架,这个框架有一些运行的机制可以让你完成编译,但是至于怎么编译是由插件决定的。还好Google已经给我们写好了Android对应的Gradle工具,我们使用就可以了。

根目录下的build.gradle中 dependencies { classpath ‘com.android.tools.build:gradle:3.2.1 } 是Android Gradle编译插件的版本。

app目录下的build.gradle中的apply plugin: ‘com.android.application’ 是引入了Android的应用构建项目,还有com.android.library和com.android.application用来构建library和应用。

所有Android构建需要执行的task都封装在工具里,如果你有一些特殊需求的话,也可以自己写一些task。那么对于开发一个Android应用来说,最关键的部分就是如何来用Android Gradle的插件了。

认知Gradle Wrapper

Android Studio中默认会使用 Gradle Wrapper 而不是直接使用Gradle。命令也是使用gradlew而不是gradle。这是因为gradle针对特定的开发环境的构建脚本,新的gradle可能不能兼容旧版的构建环境。为了解决这个问题,使用Gradle Wrapper 来间接使用 gradle。相当于在外边包裹了一个中间层。对开发者来说,直接使用Gradlew 即可,不需要关心 gradle的版本变化。Gradle Wrapper 会负责下载合适的的gradle版本来构建项目。

Android 三个文件重要的 gradle 文件

Gradle项目有3个重要的文件需要深入理解:项目根目录的 build.gradle , settings.gradle 和模块目录的 build.gradle 。

  • settings.gradle 文件会在构建的 initialization 阶段被执行,它用于告诉构建系统哪些模块需要包含到构建过程中。对于单模块项目, settings.gradle 文件不是必需的。对于多模块项目,如果没有该文件,构建系统就不能知道该用到哪些模块。
  • 项目根目录的 build.gradle 文件用来配置针对所有模块的一些属性。它默认包含2个代码块:buildscript{…}和allprojects{…}。前者用于配置构建脚本所用到的代码库和依赖关系,后者用于定义所有模块需要用到的一些公共属性。
buildscript {
  repositories {
    jcenter()
  }
 
  dependencies {
     classpath 'com.android.tools.build:gradle:3.2.1'
  }
}
 
allprojects {
  repositories {
    jcenter()
  }
}
 
task clean(type: Delete) {
  delete rootProject.buildDir

(1) buildscript:定义了 Android 编译工具的类路径。repositories中, jCenter是一个著名的 Maven仓库。
(2)allprojects:定义的属性会被应用到所有 moudle中,但是为了保证每个项目的独立性,我们一般不会在这里面操作太多共有的东西。

  • 模块级配置文件 build.gradle 针对每个moudle 的配置,这里的定义的选项和顶层
    build.gradle定义的相同。它有3个重要的代码块:plugin,android 和 dependencies。

自定义gradle插件

编写Gradle插件主要有三种方法:

  • build.gradle脚本中直接使用。这种方式就是直接在Android Studio app moudle的build.gradle中进行插件的编写,优点是不用再上传插件到maven或者其它地方,项目就可以直接使用;缺点也很明显,就是只能在自己的项目中使用,不能复用,这个不是我们今天要说的。
  • buildSrc中使用。这种方式需要在项目中新建一个model命名为buildSrc,这个目录就用来存放自定义插件。然后在src/main中建立两个目录,一个就是存放代码的groovy目录,一个是存放自定义插件名称的resources目录。这种定义方式也是只能在我们项目中进行使用,不好复用。
  • 独立Module中使用。这种方式就是完全独立开发一个Module,可以随便用。

配置

AS中新建一个Module接着就是配置目录了,和上面说的第二种方式其实一样的,配置好的目录如下,其中groovy目录就是放置代码的地方,resources里面放置的是一个配置文件。在gradle-plugins文件夹下新建一个文件com.example.watson.plugin.properties,文件的名字com.example.watson.plugin就是在使用这个插件的地方需要的名字,比如

apply plugin:'com.example.watson.plugin'

Gradle自定义插件

上面配置文件内容, 其实就是一个映射关系,找到我们定义的插件NetworkPlugin,com.example.watson.plugin是NetworkPlugin这个插件类所在的包名。

implementation-class=com.example.watson.plugin.NetworkPlugin

插件实现

环境都配置好了,接下来就是实现NetworkPlugin这个插件了,在groovy文件夹下新建包名并在该名下新建文件NetworkPlugin.groovy。当然groovy也是完全兼容Java的,所以小伙伴们看起来完全无压力啊。

定义插件首先要实现Plugin接口,然后在apply方法中实现插件功能。

class NetworkPlugin implements Plugin<Project>{

    @Override
    void apply(Project project) {
        println "------network plugin begin-------"
        project.tasks.create("networkTest", NetworkTask) {
            doLast {
                println "doLast"

            }
        }
        println "------network plugin end-------"
    }

}

为了直观感受,我添加了一个task,也就是networkTest,这个Task就是请求百度首页的网页代码并打印出来。在相同目录下新建文件NetworkTest.groovy,Task的具体工作就是@TaskAction这个注解标注的方法中了。

class NetworkTask  extends DefaultTask {

    @TaskAction
    def testNetwork() {
        println "------NetworkTask begin-------"
        try {
            OkHttpClient mOkHttpClient = new OkHttpClient()
            Request request = new Request.Builder().url("http://www.baidu.com/").build()
            Call call = mOkHttpClient.newCall(request)
            Response mResponse = call.execute()
            if (mResponse.isSuccessful()) {
                println mResponse.body().string()
            }
        } catch (Exception e) {
            e.printStackTrace()
            println e.toString()
        }
        println "------NetworkTask end-------"
    }

}

到这里我们插件的代码工作基本就完成了,剩下最后一个问题,怎么用这个插件呢?当然就是上传Maven等等的仓库中了,这里为了方便我就上传到自己的本地了。

上传插件

上传插件就是在这个Module的build.gradle中写Task了,这里我就上传到本地D盘reponsitory目录下了。

apply plugin: 'groovy'
//使用该插件,才能使用uploadArchives
apply plugin: 'maven'

repositories {
    jcenter()
}

dependencies {
    //使用gradle sdk
    compile gradleApi()
    //使用groovy sdk
    compile localGroovy()
    compile 'com.android.tools.build:gradle:3.0.1'
    //网络请求框架
    compile 'com.squareup.okhttp3:okhttp:3.7.0'
    compile 'com.squareup.okio:okio:1.9.0'
}

sourceCompatibility = "1.8"
targetCompatibility = "1.8"

uploadArchives {
    repositories.mavenDeployer {
        pom.version = '1.0.0'
        pom.artifactId = 'watsonPlugin'
        pom.groupId = 'com.example.watson.plugin'
        repository(url: "file:///D:/repository/")
    }
}

点击下build就能在plugin模块看见我们定义的uploadArchives这个Task了。
Gradle自定义插件
点击下这个任务就能在对应的目录下生成这个插件。
Gradle自定义插件

使用插件

首先在工程的根目录下的build.gradle文件下添加如下代码。maven仓库就是我们上面的仓库地址,添加依赖,其中com.example.watson.plugin就是groupId,watsonPlugin就是artifactId,1.0.0就是版本号了。

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

buildscript {
    repositories {
        google()
        jcenter()
        maven {
            url uri('D:/repository')  //add
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        classpath 'com.example.watson.plugin:watsonPlugin:1.0.0' //add
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        
    }
}

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

添加上面代码后Sync一下就能看见在引用Module的Tasks->other下面看到我们的Task了:
Gradle自定义插件
到这一步就是大功告成了,点击下这个Task就能执行请求网络和打印日志了。
Gradle自定义插件

参考:
深入理解Android之Gradle
自定义gradle插件入门
一步步自定义Gradle插件

相关标签: 进阶