一、Gradle插件的概念
Gradle是一个构建工具,让工程构建更加自动化,不过它只是一个执行环境,提供了基本的框架,真正的构建行为不是Gradle提供,Gradle负责在运行时,找到所有需要执行的任务一一去执行。
上面提到的任务有两种方式创建,一是手动创建,如在自定义任务里编译工程的java代码;二是通过插件,将相似的代码进行封装,几乎所有的功能都是以插件的形式提供。插件负责封装或者提供Gradle运行期间需要的Task,在工程中依赖某个插件后,就能复用这个插件提供的构建行为。
Android Gradle插件就是基于java插件扩展的,在编译java代码的基础上,添加了编译资源、打包APK的功能。
本文主要内容如图,
二、Gradle插件的分类
Gradle插件分为两种:二进制插件和脚本插件。
脚本插件:轻量级,独立的Gradle脚本。脚本中可以对工程的build.gradle脚本中的配置进行进一步配置或补充,既可存在于工程的目录里,又可存在于某远程服务器的地址中。
二进制插件:实现了plugin接口,可存在于独立的编译脚本里,也可作为独立的工程去维护,对外发布成插件Jar包,如Android插件。
插件最开始的形式是脚本插件,当脚本中的代码需要复用时,可将脚本插件包装成一个二进制插件,方便在不同的团队或工程进行共享。
2.1 二进制插件的用法
二进制插件的用法分为三部:声明插件的ID与版本号
1)声明插件的ID与版本号
进入根目录build.gradle,在buildscript内dependencies中通过classpath声明需要使用的插件的ID与版本号,如
classpath "com.android.tools.build:gradle:4.1.3"
然后Gradle将这个插件下载到本地。
2)应用插件
在子工程的build.gradle,通过apply应用插件,绑定插件与工程,如
apply plugin:'com.android.application'
apply plugin后面引用的名称由发布插件方在说明中给出。
3)插件参数配置(可选)
插件自定义是否需要配置,有些插件无需配置参数。如
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.router"
minSdkVersion 29
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
2.2 脚本插件的用法
在工程的根目录新建文件other.gradle,写上调试代码如
println("我是脚本插件的代码")
在子工程build.gradle应用脚本插件
apply from: project.rootProject.file("other.gradle")
三、Gradle二进制插件自定义
插件自定义包括三个步骤:建立插件工程、配置参数、发布插件与使用插件。
3.1 建立插件工程
复杂的或者需要被复用的构建逻辑可以被实现成为二进制插件,二进制插件开发形式可以有两种,一是实现成为普通的独立工程,调试时需要手动发布成Jar包给其他工程引用进行测试;二是实现成buildSrc工程,属于子工程,如果把插件的逻辑写在里面,在构建时Gradle会自动将它打包成一个二进制插件Jar包,更方便。
1)建立buildSrc子工程
建立普通工程如Router,在根目录下建立子工程buildSrc(Gradle约定必须以该名字命名),在该工程添加build.gradle文件来配置该工程。
用Gradle里面的groovy语言来实现该插件,需要依赖groovy插件编译groovy代码。声明将使用到的第三方包所属仓库。指定需要的第三方包。代码如下
//引用groovy插件,编译插件工程中的代码
apply plugin:'groovy'
//声明仓库的地址
repositories {
jcenter()
}
//声明依赖的包
dependencies {
implementation gradleApi()
implementation localGroovy()
}
2)建立插件运行入口
在buildSrc中建立源码目录,新建文件RouterPlugin.groovy,该类需要实现Plugin接口并实现apply方法,当我们采用apply关键字在工程中引用插件时,apply方法里的逻辑会被执行,可以在apply方法里注入插件的逻辑,如往工程里动态添加一个Task。代码如
package com.immoc.router.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
class RouterPlugin implements Plugin<Project> {
//实现apply方法,注入插件的逻辑
void apply(Project project) {
println("I am from RouterPlugin, apply from ${project.name}")
}
}
在META-INF.gradle-plugins文件夹下新建properties文件,添加代码
implementation-class=com.immoc.router.gradle.RouterPlugin
在app工程build.gradle应用插件如
apply plugin:'com.imooc.router'
3.2 实现参数配置
Android打包配置即参数配置,在Gradle中有特定名称叫Extension。输入我们想要配置的数据,在插件中使用,最终打出具有对应属性的apk。
实现参数配置需要4个步骤:定义Extension、注册Extension、使用Extension、获取Extension。
1)定义Extension
在Plugin同级目录新建Extension.groovy文件,添加文档保存路径参数,如
package com.immoc.router.gradle
class RouterExtension {
String wikiDir
}
2)注册Extension
在Plugin子类的apply方法中注册Extension,代码如
package com.immoc.router.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
class RouterPlugin implements Plugin<Project> {
//实现apply方法,注入插件的逻辑
void apply(Project project) {
//注册Extension
project.getExtensions().create("router", RouterExtension)
}
}
3)使用Extension
在应用该插件的build.gradle文件中,使用Extension的代码放在apply该插件的后面,如给wikiDir传参,
apply plugin:'com.imooc.router'
router {
wikiDir getRootDir().absolutePath
}
4)获取Extension
gradle的生命周期在配置阶段会把gradle脚本即build.gradle里所有配置代码执行一遍,在配置阶段结束后能获取到相关配置,当Project的afterEvaluate方法执行后代表配置阶段结束,在这里获取配置,如代码,
package com.immoc.router.gradle
import org.gradle.api.Plugin
import org.gradle.api.Project
class RouterPlugin implements Plugin<Project> {
//实现apply方法,注入插件的逻辑
void apply(Project project) {
//注册Extension
project.getExtensions().create("router", RouterExtension)
//获取Extension
project.afterEvaluate {
RouterExtension extension = project["router"]
}
}
}
3.3 发布插件
由于该插件使用buildSrc子工程的形式,该插件在当前工程中可以直接使用。如果要给其他团队的开发者使用,就要将插件发布成二进制Jar包,可以发布到本地仓库和远程仓库。
以发布到本地仓库为例,发布插件到Maven仓库,需要调用maven插件,并配置来自Maven插件名为uploadArchives的Task,uploadArchives是一个Upload Task,用于上传发布我们的构件。在buildSrc的build.gradle文件中如下配置,
//调用maven插件,用于发布
apply plugin: 'maven'
//配置maven插件中的uploadArchives任务
uploadArchives {
repositories {
mavenDeployer{
//设置发布路径为 工程根目录下面的 repo文件夹
repository(url:uri('../repo')) {
//设置groupId,通常为包名
pom.groupId = 'com.imooc.router'
//设置artifactId,为当前插件的名称
pom.artifactId = 'router-gradle-plugin'
//设置 插件的版本号
pom.version = '1.0.0'
}
}
}
}
由于不能在buildSrc中发布,需要将buildSrc目录拷贝一份,更改名称如router-gradle-plugin,新工程注册到settings.gradle,如,
include ':app',':router-gradle-plugin'
调用命令“gradlew :router-gradle-plugin:uploadArchives”进行发布
3.4 在工程中应用插件
在工程中应用发布好的二进制插件,在该工程根目录build.gradle文件中buildscript和allprojects的repositories包下配置maven仓库地址,如
/*
*1、配置maven仓库地址
*这里可以时相对路径,也可以时绝对路径
*/
maven {
url uri("D:\\Android Studio\\AndroidStudioProjects\\Router\\repo")
}
然后告诉Gradle需要用仓库里的哪些插件,在buildscript的dependencies包下配置
/*
*2、声明依赖的插件
*形式是:groupId : artifactId : version
*/
classpath 'com.imooc.router:router-gradle-plugin:1.0.0'
在需要应用插件的工程的模块的build.gradle文件中应用插件,并把参数传递给插件,如
/*
*3、应用插件
*/
apply plugin:'com.imooc.router'
/*
*4、向插件传递参数
*/
router {
wikiDir getRootDir().absolutePath
}
作者:she_says
链接:https://juejin.cn/post/6982900575482413064
关注我获取更多知识或者投稿