Android知识要点整理(21)----Gradle 之创建任务和插件
Posted znapast
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android知识要点整理(21)----Gradle 之创建任务和插件相关的知识,希望对你有一定的参考价值。
1.定义Tasks
先看创建Tasks的代码示例:
//方式1
task hello
//方式2
task hello
println 'Hello, world!'
//方式3
task hello <<
println 'Hello, world!'
//方式4
task(hello) <<
println 'Hello, world!'
//方式5
task('hello') <<
println 'Hello, world!'
//方式6
tasks.create(name: 'hello') <<
println 'Hello, world!'
上面六种方式都创建了一个名为 hello
的task.但是他们是有区别的,方式1是个空任务,它不会干任何事;方式2和方式3在代码上看就差一个双箭头,但是它们是有本质区别的;方式2中,打印“hello,world“字符串的语句会在执行任务之前运行,而方式3会在执行任务的时候打印出”hello,world”,也就是说**方式2中的语句实在configuration阶段执行的,方式3中语句则是在execution阶段执行的;方式4、5、6是方式3的不同表现形式,本质上是一样的。看如下代码执行的结果:
task hello <<
println 'Execution'
hello
println 'Configuration'
执行结果如下:
$ gradlew hello
Configuration
:hello
Execution
再看一种比较复杂的定义Task的方式,这种方式使用了doFirst 和doLast 代码块,它可以控制代码执行的先后顺序:
task mindTheOrder
println 'Configuration'
doFirst
println 'Not really first.'
doFirst
println 'First!'
doLast
println 'Not really last.'
doLast
println 'Last!'
执行结果如下:
$ gradlew mindTheOrder
Configuration
:mindTheOrder
First!
Not really first.
Not really last.
Last!
2.Tasks之间的依赖
如果要决定tasks之间执行的先后顺序,我们可以有2种方式:
第一种 使用mustRunAfter
方法,示例代码如下:
task task1 <<
println 'task1'
task task2 <<
println 'task2'
//定义task2必须在task1之后执行
task2.mustRunAfter task1
看看执行命令的结果:
$ gradlew task2 task1
:task1
task1
:task2
task2
可以看出,虽然指定参数时task2在task1之前,但是task2实际是在task1执行完后才执行的。需要强调的是,task2并不需要task1必须有,如果没有指定task1,task2仍然会执行。
第二种方式就是使用 dependsOn
方法。看示例:
task task1 <<
println 'task1'
task task2 <<
println 'task2'
task2.dependsOn task1
看看命令的执行结果:
$ gradlew task2
:task1
task1
:task2
task2
可以看出,虽然命令参数没有指定task1,但是执行时还是先执行了task1,再执行task2,task2的执行必须要有task1的执行。这个是dependsOn方法和mustRunAfter方法的主要区别。
3.Task实例
下面定义task用来获取签名密码。先创建一个属性文件private.properties.内容如下:
//定义密码
release.password = thepassword
然后定义一个task,用于从属性文件中读取密码。代码如下:
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')
//如果密码为空,则在命令行界面提示用户输入密码
if (!password?.trim())
password = new String(System.console().readPassword
("\\nWhat's the secret password? "))
//将密码赋值给签名配置
android.signingConfigs.release.storePassword = password
android.signingConfigs.release.keyPassword = password
自此,完整的任务已经定义好了。下一步就是如何触发它的执行。方法如下:
//任务载入到gradle模型时会执行下面的方法
//方法通过添加依赖关系来触发上面定义的任务的执行
tasks.whenTaskAdded theTask ->
if (theTask.name.equals("packageRelease"))
theTask.dependsOn "getReleasePassword"
4.定制构建过程
如何影响Android的构建过程,一种方式如下所示:
android.applicationVariants.all variant ->
// Do something
上述代码遍历APP所有的构建变体,我们可以针对特定的构建变体定义自己的逻辑。比如,重命名生成的apk文件。代码示例如下:
//针对libray,则需要使用libraryVariants对象
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"))
再比如,动态创建task,示例如下:
android.applicationVariants.all variant ->
if (variant.install)
//为每个构建变体创建一个run任务
//run任务依赖install任务
tasks.create(name: "run$variant.name.capitalize()",
dependsOn: variant.install)
description "Installs the $variant.description and runs
the main launcher activity."
//执行启动主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]
5.自定义插件
插件可以看作是一些列task的集合。为了创建插件,我们需要实现Plugin接口。简单的插件代码示例如下:
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)
// 定义任务逻辑
定义好了插件,我们通过如下代码来应用到项目中:
apply plugin: RunPlugin
如果我们想将插件打包为jar文件,以便其他项目也可以使用,那我们需要创建一个Groovy 模块。和其他模块一样,需要有一个build.gradle文件。内容如下:
//需要应用groovy插件,表示这是一个groovy模块
apply plugin: 'groovy'
//添加gradle相关的依赖,因为定义插件需要用到gradle 相关的api
dependencies
compile gradleApi()
compile localGroovy()
然后确保模块中有如下的目录结构:
plugin
└── src
└── main
├── groovy
│ └── com
│ └── package
│ └── name
└── resources
└── META-INF
└── gradle-plugins
然后我们可以在com/package/name目录下创建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能够发现这个插件,需要在META-INFO/gradle-plugins目录下创建一个独特的文件。这个文件的名称必须和插件的ID匹配,对于RunPlugin插件,文件名对应为com.gradleforandroid.run.properties
,也就是package+插件名称(Run)。文件内容也很独特,它用于指定实现插件的类名,内容如下:
implementation-class=com.gradleforandroid.RunPlugin
然后我们就可以指定gradlew assemble
命令来生成jar包了。
最后可以将jar包加入到任意项目,然后在项目的根目录的build.gradle文件中添加如下代码:
buildscript
repositories
flatDir dirs 'build_libs'
dependencies
//指定插件的类路径:包名+plugin
classpath 'com.gradleforandroid:plugin'
//最后就可以应用该插件了
apply plugin: com.gradleforandroid.RunPlugin
至此,定义task和插件的方法就讲完了。
以上是关于Android知识要点整理(21)----Gradle 之创建任务和插件的主要内容,如果未能解决你的问题,请参考以下文章
Android 知识要点整理(12)----Animation(动画)