目前为止,我们已经学习了如何修改Gradle构建属性,以及如何运行任务。本章,我们会深入了解这些属性,并且创建我们自己的任务。一旦我们学会了创建任务,就可以更进一步,学习如何创建Gradle插件。
在学习创建任务之前,我们需要学习一些重要的Groovy概念。因为了解一些Groovy基础有助于我们自定义任务和插件。学习Groovy也可以帮助我们了解Gradle的原理,以及构建文件的书写格式。
本章内容有:
- 了解Groovy
- 学习任务
- 接入Android插件
- 创建插件
了解Groovy
由于多数Android开发者精通Java,所以将Groovy和Java对比学习相对要容易一些。Groovy对于Java开发者来说很容易阅读,但如果不简单了解一下的话,编写起来还是有一定难度的。
使用Groovy Console来学习Groovy是一个很好的途径。这个应用包含在Groovy SDK中,可以立即执行Groovy代码得到结果。Groovy Console也可以运行纯Java代码,可以更加方便的对比Java和Groovy代码。你可以从http://groovy-lang.org/download.html下载带有Groovy Console的Groovy SDK。
简介
Groovy源自Java,并在JVM上运行。Groovy是一种简单、直接的语言,既是脚本,也是一种成熟的编程语言。本节我们通过对比来了解Groovy的原理以及和Java的不同。
Java打印字符串代码如下:
System.out.println("Hello, world!");
而Groovy如下:
println 'Hello, world!'
两者有几个关键的不同之处:
- 没有
System.out
命名空间 - 方法的参数没有加圆括号
- 语句末尾没有分号
示例同样在字符串的两侧使用了单引号。你也可以使用双引号,但两者作用不完全一样。双引号的字符串可以包含插值表达式。插值是计算包含占位符的字符串的过程,并将占位符替换为真实值。占位符表达式可以是变量或者方法。包含方法或者多个变量的占位符表达式需要放入{}
中,并以$
作为前缀;仅包含单个变量的占位符表达式只需要以$
为前缀。下面是一些例子:
def name = 'Andy'
def greeting = "Hello, $name!"
def name_size "Your name is ${name.size()} characters long."
greeting
变量的值是"Hello, Andy",name_size
的值是"Your name is 4 characters long."。
字符串插值也可以允许你动态执行代码,如下:
def method = 'toString'
new Date()."$method"()
如果你已经习惯了java,这看起来会很陌生,但这是动态编程语言的正常的语法和行为。
类和成员
Groovy创建类和Java很相似。下面是包含一个成员的类:
class MyGroovyClass {
String greeting
String getGreeting() {
return 'Hello!'
}
}
注意类和成员都没有明确的访问修饰符。Groovy默认的访问修饰符和Java不一样。类和方法默认是public的,成员默认是private的。
下面创建MyGroovyClass
的实例:
def instance = new MyGroovyClass()
instance.setGreeting 'Hello, Groovy!'
instance.getGreeting()
你可以使用def
关键字来创建新的变量。在有了类的示例之后,你就可以操作类成员了。Groovy会自动添加成员的访问器。你也可以覆写它们,比如这里我们覆写了getGreeting()
方法。
你也可以直接调用成员,这实际也是在调用getter方法。也就是说你可以输入instance.greeting
来代替instance.getGreeting()
:
println instance.getGreeting()
println instance.greeting
两种方式结果一样。
方法
和变量相似,你不需要为方法指定返回类型。你可以这么做,哪怕只是为了简洁。Groovy和Java方法的另一个不同之处是最后一行默认是返回值,即使没有使用return
关键字。
为了展示Java和Groovy方法的不同,参照下面的Java方法:
public int square(int num) {
return num * num;
}
square(2);
你需要指定方法的访问类型、返回值类型、参数类型,并在最有一行使用return
关键字。
在Groovy中,这个方法如下:
def square(def num) {
num * num
}
square 4
返回值类型和参数类型不必指明。def
关键字取代了明确的类型,返回值不需要return
关键字。尽管如此,为了清晰,还是推荐使用return
关键字。调用方法时,你不必为它添加圆括号。
下面是Groovy更简洁的定义方法的形式:
def square = { num ->
num * num
}
square 8
这不是一个常规的方法,而是一个闭包。Java没有类似闭包的概念。闭包在Groovy和Gradle中有非常重要的作用。
Closures(闭包)
闭包是一个可以有输入和输出的匿名代码块。它可以用来给变量赋值,也可以作为方法的参数。
你可以在花括号中添加代码块来定义简单的闭包。如果你想更明确一点,你可以将类型添加到定义中:
Closure square = {
it * it
}
square 16
Closure
显示指明了代码块的类型为闭包。前面的示例还介绍了隐式无类型参数it
的概念。如果你没有为闭包显示添加参数,Groovy会自动添加一个,参数名为it
,你可以在所有闭包中使用它。如果调用者没有指定任何参数,it
的值为null。这使代码稍微简洁一些,但只在有单个参数时有效。
在Gradle中,我们每时每刻都在使用闭包。本书中,目前为止我们说的块就是指闭包。也就是说,android
块和dependencies
块都是闭包。
集合
在Gradle中使用Groovy时,有两个集合类型:list和map。
Groovy创建list非常简单。只需要:
List list = [1, 2, 3, 4, 5]
list的遍历也非常简单。可以使用each
方法:
list.each() { element ->
println element
}
你也可以使用it
来精简代码:
list.each() {
println it
}
map在Gradle的一些配置和方法中使用。map是一个键值对的集合,可以如下定义:
Map pizzaPrices = [margherita:10, pepperoni:12]
可以使用get
方法或者方括号来访问map。
pizzaPrices.get('pepperoni')
pizzaPrices['pepperoni']
Groovy还有一个更加简单的方式。可以直接使用map.key
的语法来得到相应的值:
pizzaPrices.pepperoni
Groovy in Gradle
现在我们已经了解了Groovy的基础,是时候回过头来重新看下Gradle的构建文件了。我们可以比较容易地理解配置语法。比如,Android插件是如何被引入构建的:
apply plugin: 'com.android.application'
这块代码使用了Groovy的简写。完全不简写的话,它是这个样子的:
project.apply([plugin: 'com.android.application'])
这样理解起来局容易多了。apply
是Project
类的一个方法,接收一个map
参数,其中键为plugin
,值为com.android.application
。
另一个例子是dependencies
块:
dependencies {
compile 'com.google.code.gson:gson:2.3'
}
现在我们知道了这个块是一个闭包,作为Project
类dependencies()
方法的参数。这个闭包会传递给DependencyHandler
对象,该对象有add()
方法。这个方法由三个参数:一个定义配置的字符串,一个定义依赖符号的对象,一个包含这个依赖的属性的闭包。它的全写如下:
project.dependencies({
add('compile', 'com.google.code.gson:gson:2.3', {
// Configuration statements
})
})
到现在为止你应该已经可以看懂这些配置文件了。
如果你想学习更多Gradle是如何使用Groovy的,你可以从看Project的官方文档看起,地址为: http://gradle.org/docs/current/javadoc/org/gradle/api/Project.html
学习任务
自定义Gradle任务可以显著提高开发者的效率。任务可以操作已有的构建过程,添加新的构建阶段,或者影响构建的输出。你可以执行简单的任务,比如重命名生成的APK。任务可以使你运行更为复杂的代码,比如在app打包前,生成几个不同密度的图像。在学会创建任务之后,你就有能力去改变构建过程的方方面面。当你学习如何使用Android插件时,这一点尤其正确。
定义任务
任务属于一个Project
对象,每个任务都实现了Task
接口。最简单的定义任务的方法是执行task
方法,并将任务名称传递给它:
task hello
这就创建了一个任务,但是执行它不会做任何事情。想要创建一个稍微有点作用的任务,你需要为它添加动作。初学者常犯的一个错误是这样创建任务:
task hello {
println 'Hello, world!'
}
执行的结果如下:
$ gradlew hello
Hello, world!
:hello
从结果看,你可能认为这个任务做事情了,但实际上,"Hello,world!"是在任务执行之前打印出来的。为了理解这个地方发生了什么,我们需要回过头来看下基础的东西。在第一章,我们学习了Gradle构建的生命周期:初始化阶段、配置阶段和执行阶段。在你像上例中那样添加任务时,你实际上设置了任务的配置。即使你执行其他的任务,"Hello,world!"也会打印。
如果你想在执行阶段为任务添加动作,使用如下方式:
task hello << {
println 'Hello, world!'
}
唯一的区别是闭包前的<<
符号。这会告知Gradle这段代码是为执行阶段准备的,而不是配置阶段。
为了展示它们的区别,看下面的构建文件:
task hello << {
println 'Execution'
}
hello {
println 'Configuration'
}
我们定义了任务hello
,在执行时会打印"Execution"。我们也为hello
任务的配置阶段定义了代码,即打印"Configuration"。即使配置块是在真正的任务定义代码之后定义的,它也会先被执行。上例的输出为:
$ gradlew hello
Configuration
:hello
Execution
错误的使用配置阶段导致任务失败是一个很常见的错误。在创建任务时需要牢记。
由于Groovy有很多简写,Gradle定义任务有如下几种形式:
task(hello) << {
println 'Hello, world!'
}
task('hello') << {
println 'Hello, world!'
}
tasks.create(name: 'hello') << {
println 'Hello, world!'
}
前两个块是Groovy实现相同功能的两种不同方式。你可以使用圆括号,但不是必须的。你也可以不用单引号。在这两个块中,我们调用了task()
方法,它需要两个参数:一个任务名称和一个闭包。task()
方法是Project
类的方法。
最有一个块没有使用task()
方法,而是使用了Project
类的tasks
对象,该对象是TaskContainer
的实例。这个类提供了一个create()
方法,接收一个Map
和一个闭包作为参数,返回一个Task
。
使用简写是非常便捷的书写方式,很多在线的示例和教程都是使用的简写。而全写对初次学习非常有用,这样,Gradle才看起来不那么神奇,理解起来更加容易。
任务剖析
Task
接口是所有任务的基础,定义了属性和方法的集合。所有这些被DefaultTask
类实现。这是一个标准的任务类型的实现,在你定义一个新的任务时,它是基于DefaultTask
的。
从技术上讲,
DefaultTask
并不是真正的Task
接口所有方法的实现类。Gradle有一个名为AbstractTask
的内部类,包含所有方法的实现。因为AbstractTask
是内部类,我们不能继承它。所以我们才关注继承自AbstractTask
的DefaultTask
类,并覆写它。
每个任务有一个Action
对象的集合。在执行任务时,所有的动作会被顺序执行。你可以使用doFirst()
和doLast()
方法添加动作。这两个方法都以闭包作为参数,然后将其封装成一个Action
对象。
你只有使用doFirst()
或者doLast()
方法才能为任务添加在执行阶段运行的代码。我们之前使用的左移操作符<<
是doFirst()
方法的简写。
下面是使用这两个方法的例子:
task hello {
println 'Configuration'
doLast {
println 'Goodbye'
}
doFirst {
println 'Hello'
}
}
执行hello任务,输出如下:
$ gradlew hello
Configuration
:hello
Hello
Goodbye
你也可以多次调用doFirst()
和doLast()
:
task mindTheOrder {
doFirst {
println 'Not really first.'
}
doFirst {
println 'First!'
}
doLast {
println 'Not really last.'
}
doLast {
println 'Last!'
}
}
该任务的输出为:
$ gradlew mindTheOrder
:mindTheOrder
First!
Not really first.
Not really last.
Last!
注意doFirst()
总是将动作加到任务的开头,doLast()
总是加到末尾。你在使用这样的方法时需要谨慎,尤其是对顺序有要求时。
对于需要顺序执行的任务,你可以使用mustRunAfter()
方法。这个方法允许你改变Gradle构建的依赖图。
task task1 << {
println 'task1'
}
task task2 << {
println 'task2'
}
task2.mustRunAfter task1
同时执行两个任务,task1总会在task2之前运行:
$ gradlew task2 task1
:task1
task1
:task2
task2
mustRunAfter()
方法并没有在任务间添加依赖,你仍然可以单独执行task2,而不必执行task1。如果你需要让一个任务依赖另一个任务,可以使用dependsOn()
方法。mustRunAfter()
和dependsOn()
的区别可以从下面的示例提现:
task task1 << {
println 'task1'
}
task task2 << {
println 'task2'
}
task2.dependsOn task1
单独执行task2,得到的结果如下:
$ gradlew task2
:task1
task1
:task2
task2
使用mustRunAfter()
,在同时执行task1、task2时,task1总是在task2之前执行,但是它们仍然可以单独执行。而使用dependsOn()
,单独执行task2总会先触发执行task1。这是一个明显的不同之处。
使用任务来简化发布过程
在你将应用发布到Google Play商店之前,你需要用证书进行签名。你需要有自己的keystore,它包含一组私钥。在你有了keystore和私钥之后,可以在配置文件中定义签名配置:
android {
signingConfigs {
release {
storeFile file("release.keystore")
storePassword "password"
keyAlias "ReleaseKey"
keyPassword "password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
这种方法的缺点是,你的keystore的密码以纯文本的方式保存在仓库中。如果你是在做开源项目,这是绝对不行的;任何一个有keystore文件和私钥的人可以用你的身份发布应用。为了防止这种情况的发生,你需要创建一个任务,在每次生成发布包时,查询发布密码。虽然这有点麻烦,但它确实能使构建服务器自动生成发布版本。一个不错的保存keystore密码的解决方案是创建一个不保存在仓库中的配置文件。
在项目的根目录创建一个private.properties
文件,添加如下代码:
release.password = thepassword
我们假设keystore和key本身的密码相同。如果你的密码不同,也可以添加第二个属性。
设置好这些,你可以定义一个getReleasePassword
的任务:
task getReleasePassword << {
def password = ''
if (rootProject.file('private.properties').exists()) {
Properties properties = new Properties();
properties.load( rootProject.file('private.properties').newDataInputStream())
password = properties.getProperty('release.password')
}
}
这个任务会在项目根目录查询一个名额外private.properties
的文件。如果文件存在,该任务会加载所有的属性信息。properties.load()
方法会查询键值对,比如我们定义的release.password
。
为了确保任何人在没有private.properties
文件或者属性文件存在,但没有release.password
属性的情况下都可以运行脚本,需要添加一个反馈。如果密码为空,在控制台要求输入密码:
if (!password?.trim()) {
password = new String(System.console().readPassword("\nWhat's the secret password? "))
}
Groovy检查字符串是否为空是非常简单的。password?.trim()
中的问号是一个null检查,在password为null时,不会调用trim()
方法。我们不用进行明确的空判断,因为空的字符串在if
语句中会返回false
。
new String()
是必须的,因为System.readPassword()
会返回一个字节数组,我们需要显示转换为字符串。
在有了keystore的密码之后,我们就可以为release版本配置签名配置了。
android.signingConfigs.release.storePassword = password
android.signingConfigs.release.keyPassword = password
任务写完了,我们还要确保被执行。在build.gradle
文件中添加如下代码:
tasks.whenTaskAdded { theTask ->
if (theTask.name.equals("packageRelease")) {
theTask.dependsOn "getReleasePassword"
}
}
这段代码会将一个闭包与Gradle和Android插件挂钩,在任务检入依赖图时,代码会被执行。packageRelease
执行之前,不会要求密码,所以我们确保packageRelease
依赖getReleasePassword
任务。我们不可以仅仅使用packageRelease.dependsOn()
,因为打包任务是Android插件动态生成的,依赖于构建变体。也就是说,在Android插件查询到所有的构建变体之前,packageRelease
任务是不存在的。这个查找过程在构建之前开始。
想要这个任务工作,跟Gradle和Android插件挂钩是必须的。这是一个强有力的概念,我们会探索更多的细节。
与Android插件挂钩
在Android开发中,我们想要影响的多数任务都和Android插件相关。可以通过挂钩构建过程来增加任务的行为。上例我们学习到了在常规构建中,怎样向一个Android任务添加新的依赖任务。本节,我们将研究一些Android特有构建的钩子。
一个挂钩Android插件的方法是修改构建变体。这么做非常直接,你只需要用下面的代码片段就可以遍历所有的构建变体:
android.applicationVariants.all { variant ->
// Do something
}
你可以使用applicationVariants
对象来获取构建变体的集合。拿到构建变体的引用后,你就可以访问和更改它的属性了,比如name,description等。如果你想在Android library上使用相同的逻辑,可以使用libraryVariants
对象。
注意我们遍历构建变体时,使用的是
all()
而不是each()
方法。因为each()
的触发是在evaluation阶段,在Android插件创建构建变体之前。all()
方法在每次集合加入新元素时就会触发。
这个钩子可以用来在APK保存之前修改名称,或者在文件名中添加版本号。这就使维护APK变得容易,因为你不需要手动编辑文件名。下一节我们会学习如何实现它。
自动重命名APK
一个常见的修改构建构成的应用场景是在APK打包后,重命名以包含版本信息。你可以遍历应用的构建变体,修改outputFile
属性来达到目的:
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def file = output.outputFile
output.outputFile = new File(file.parent,file.name.replace(".apk", "-${variant.versionName}.apk"))
}
}
每个构建变体有一个输出的集合。一个Android应用的输出是一个APK。每个输出对象有一个File
类型的属性outputFile
。知道了输出的路径之后,你就可以修改它。本例中我们在文件名中加入了版本信息。
强大的Android插件钩子和简洁的Gradle任务的结合给了我们无限的可能。下一节,我们学习如何为应用的每个构建变体创建一个任务。
动态创建任务
基于Gradle的工作方式和任务的构造方式,在Android构建变体的基础上,我们可以在配置阶段创建新的任务。为了展示这个强大的概念,我们将创建一个任务,用来安装、运行Android应用的任何一个构建变体。install
任务是Android插件定义的,但是如果你是用命令行运行installDebug
任务来安装应用,安装结束后,你需要手动启动它。本节我们将创建的任务会解决最后一步的问题。
首先与applicationVariants
属性挂钩:
android.applicationVariants.all { variant ->
if (variant.install) {
tasks.create(name: "run${variant.name.capitalize()}", dependsOn: variant.install) {
description "Installs the ${variant.description} and runs the main launcher activity."
}
}
}
对每一个变体,检查它是否有install
任务。这是必需的,因为我们要创建的新的任务需要依赖于它。确定install
任务存在后,我们基于变体的名称创建一个新任务,该任务依赖于variant.install
,执行时会触发install
任务。task.create()
的闭包中添加了描述字段,在执行gradlew tasks
时会显示出来。
除了添加描述外,我们还需要添加任务执行的动作。本例中,我们想要启动应用。Android Debug Tool(ADB)提供了启动真机或者模拟器应用的命令:
$ adb shell am start -n com.package.name/com.package.name.Activity
Gradle有一个exec()
的方法,可以执行命令行。为使exec()
工作,我们需要加到PATH环境变量中。我们同样需要把所有的参数传递给args
属性:
doFirst {
exec {
executable = 'adb'
args = ['shell', 'am', 'start', '-n',"${variant.applicationId}/.MainActivity"]
}
}
为了获取包名,可以使用构建变体的applicationId,它可能包含一个后缀(如果提供的话)。在这个例子中,后缀会有一个问题。即使我们添加了后缀,activity的路径也是不会变的,比如:
android {
defaultConfig {
applicationId 'com.gradleforandroid'
}
buildTypes {
debug {
applicationIdSuffix '.debug'
}
}
}
包名是com.gradleforandroid.debug
,但是activity的路径依然是com.gradleforandroid.Activity
。为了得到正确的路径,我们需要去掉后缀:
doFirst {
def classpath = variant.applicationId
if(variant.buildType.applicationIdSuffix) {
classpath -= "${variant.buildType.applicationIdSuffix}"
}
def launchClass = "${variant.applicationId}/${classpath}.MainActivity"
exec {
executable = 'adb'
args = ['shell', 'am', 'start', '-n', launchClass]
}
}
首先,我们创建了一个classpath
变量,并赋值为applicationId。接下来,查找后缀。在Groovy中,字符串可以使用-
做减法。这些更改确保在添加后缀的情况下,应用安装完成后可以自动运行。
创建插件
如果你有一些想要在多个工程中复用的任务,可以考虑将任务提取到自定义的插件中。这样你就可以复用构建逻辑,或者将它分享出去。
插件可以由Groovy编写,也可以基于JVM的其它语言,比如Java、Scala。实际上,Gradle Android插件的大部分是有Java和Groovy混合编写的。
创建一个简单的插件
为了提取构建文件中的构建逻辑,你可以在build.gradle
文件中创建一个插件。这是最简单的自定义插件的方式。
为了创建插件,首先需要创建一个实现了Plugin
接口的类。我们将使用本章已写过的动态创建run
任务的代码。插件类如下:
class RunPlugin implements Plugin<Project> {
void apply(Project project) {
project.android.applicationVariants.all { variant ->
if (variant.install) {
project.tasks.create(name:"run${variant.name.capitalize()}", dependsOn: variant.install) {
// Task definition
}
}
}
}
}
Plugin
接口定义了apply()
方法。构建文件使用插件时,Gradle会调用这个方法。project
会作为参数传递过来,这样插件就可以配置项目或者使用项目的方法和属性。在上一个例子中,我们不能从Android插件直接调用属性,而是应该首先访问project对象。需要注意的是,这要求Android插件在我们的插件之前被引入到项目中,否则,project.android
会引发异常。
任务的代码和之前是一样的,只是exec()
需要用project.exec()
替换。
将该插件引入到构建文件中:
apply plugin: RunPlugin
分发插件
为了分发插件并分享给其他人,你需要将它移动到一个单独的模块(或项目)中。单独的插件有它自己的构建文件来配置依赖和分发的方法。这个模块生成一个JAR文件,包含插件类和属性。你可以使用这个JAR文件将插件应用到模块或者项目中,也可以分享给他人。
和其他Gradle项目一样,创建一个build.gradle
来配置构建:
apply plugin: 'groovy'
dependencies {
compile gradleApi()
compile localGroovy()
}
由于我们是用Groovy写的插件,所以需要引入Groovy插件。Groovy插件继承自Java插件,使我们可以构建和打包Groovy类。Groovy同样支持Java,你可以混合使用。你甚至可以使用Groovy扩展Java类。这使Groovy很容易上手。
gradleApi()
依赖用于在我们的插件中访问Gradle的命名空间。
localGroovy()
依赖是Groovy SDK在Gradle中安装的发行版。
这两个依赖是Gradle自动添加的。
如果你计划公开发布你的插件,请确保在构建文件中定义了group和version信息,例如
group = 'com.gradleforandroid'
version = '1.0'
为了使用独立模块的代码,我们还需要确保正确的目录结构:
plugin
└── src
└── main
├── groovy
│ └── com
│ └── package
│ └── name
└── resources
└── META-INF
└── gradle-plugins
和其他的Gradle模块一样,我们需要提供一个src/main
目录。因为这是一个Groovy工程,所以main的子目录是groovy
而不是java
。main的另一个子目录是resources
,用来指定插件的属性。
我们在包目录创建了一个RunPlugin.groovy
的类文件:
package com.gradleforandroid
import org.gradle.api.Project
import org.gradle.api.Plugin
class RunPlugin implements Plugin<Project> {
void apply(Project project) {
project.android.applicationVariants.all { variant ->
// Task code
}
}
}
为使Gradle能够找到插件,我们需要提供一个属性文件。将属性文件添加到src/main/resources/META-INF/gradle-plugins/
目录。文件名需要匹配插件的ID。对于RunPlugin
来说,属性文件名称为com.gradleforandroid.run.properties
,它的内容是:
implementation-class=com.gradleforandroid.RunPlugin
属性文件内容仅仅是实现了Plugin接口的类的包名和类名。
准备好接口和属性文件后,我们可以使用gradlew assemble
命令来构建插件,这会在构建输出目录创建一个JAR文件。如果你想将插件上传到Maven仓库,你首先需要引入Maven插件:
apply plugin: 'maven'
然后,你需要配置uploadArchives
任务:
uploadArchives {
repositories {
mavenDeployer {
repository(url: uri('repository_url'))
}
}
}
uploadArchives
是预定义的任务。为这个任务配置了仓库之后,你就可以运行它来发布你的插件。本书不会讲述如何设置Maven仓库。如果你想让你的插件公开可用,可以发布到Gradleware的插件门户(https://plugins.gradle.org)。插件门户有一大批Gradle插件(不仅仅是Android的),如果你想扩展Gradle的默认行为,可以去浏览一下。你在https://plugins.gradle.org/docs/submit网站可以学习如何发布插件。
为自定义插件写测试不是本书的内容,如果你想公开发布插件,强烈建议进行测试。你可以在Gradle用户指南https://gradle.org/docs/current/userguide/custom_plugins.html#N16CE1学习编写测试
使用自定义插件
要使用插件,需要在buildscript
块将其添加为依赖。首先,我们需要配置一个新仓库。仓库的配置依赖于插件发布的途径。其次,我们需要在dependencies
块配置插件的类路径。
如果你想引入上例创建的JAR文件,可以定义一个flatDir
仓库:
buildscript {
repositories {
flatDir { dirs 'build_libs' }
}
dependencies {
classpath 'com.gradleforandroid:plugin'
}
}
如果已经将插件上传到Maven或者Ivy仓库,配置会有所不同。我们在第3章讲了配置管理,所以我们将不再讲述不同之处。
配置好之后,我们需要应用插件:
apply plugin: com.gradleforandroid.RunPlugin
在使用apply()
方法的时候,Gradle会创建一个插件类的实例,并执行插件自己的apply()
方法。