在讲解Task之前,先了解Gradle核心之Project详解及实战
Project相关的API
获取Project
查看所有的Project,在Gradle中为我们提供了Task任务projects,执行下面命令后,会列出所有的Project
> gradlew projects
// 执行上面命令后,列出所有的project,包括Root project
------------------------------------------------------------
Root project
------------------------------------------------------------
Root project 'walletApp'
\--- Project ':app
我们可以通过Project提供的API访问所有的project。getAllprojects返回所有的project,包括当前project,返回类型:Set集合
def getMyAllProjects() {
println "-------------------------------------"
println "Root Project"
println "-------------------------------------"
// 获取所有project,包括本身
this.getAllprojects().eachWithIndex { Project project, int index ->
if (index == 0) {
println "Root Project: ${project.name}"
} else {
println "+---- Project: ${project.name}"
}
}
}
也提供了getSubprojects返回所有子project,返回类型:Set集合
def getMySubprojects() {
println "-------------------------------------"
println "Sub Project"
println "-------------------------------------"
// 获取所有子project
this.getSubprojects().eachWithIndex { Project project, int index ->
println "+---- Project: ${project.name}"
}
}
除了上面两种方式,还提供了获取 Parent project和 Root project ,对应的方法分别是getParent() 和 getRootProject()。他们主要区别是,getParent()如果本身就是Root Project,则返回null;而getRootProject()如果本身就是Root Project,返回Root project,不会返回null
/**
* 获取父Project, 如果本身就是Root Project,返回null
*/
def getMyParentProject() {
// The parent project, or null if this is the root project.
if (this.getParent()) {
println "the parent project name is : ${this.getParent().name}"
} else {
println "the parent project is null"
}
}
/**
* 获取Root Project,如果本身就是Root Project,返回自己,不会返回null
*/
def getMyRootProject() {
// The root project. Never returns null.
def name = this.getRootProject().name
println "the root project name is: ${name}"
}
统一配置Project
可以在Root project中通过Project提供的project方法对单个project进行独立配置,如应用插件、project分组、project版本、依赖等信息
project('app') { Project project ->
project.apply plugin: 'com.android.application'
project.group 'com.yqb.mm'
project.version '1.0.0'
project.dependencies {
}
}
每个Project都会有一个Build文件,可以通过Project提供的subprojects 或者 allprojects 可以对Child Project统一配置
this.subprojects {
println "The project name is ${project.name}"
}
// 输出日志信息
The project name is app
The project name is basiclib
属性相关的API
Project默认提供下面几种属性,从下图中可以看出,为什么gradle中build文件名是build.gradle了。
除了Project默认提供的,我们也可以通过ext关键字自定义属性。下面是我们自定义的应用包名、版本信息、依赖、签名文件等相关信息。
ext {
applicationId = "com.kerwin.test"
// android sdk version
// 使用如下:
// def versions = rootProject.ext.versions
// compileSdkVersion versions.compileSdkVersion
// buildToolsVersion versions.buildToolsVersion
versions = [
compileSdkVersion: 26,
minSdkVersion : 19,
targetSdkVersion : 26,
versionCode : 182,
versionName : '1.8.2',
]
// dependencies
// 使用如下:
// def dependencies = rootProject.ext.dependencies
// compile dependencies.support.appcompat
dependencies = [
support : [
appcompat : "com.android.support:appcompat-v7:26.1.0",
constraint: "com.android.support.constraint:constraint-layout:1.1.3",
design : "com.android.support:design:26.1.0"
],
gson : "com.google.code.gson:gson:2.8.5"
]
signingConfigs = [
debug: [
storeFile : '../keystore/mm_debug.keystore',
storePassword: 'pa123456',
keyAlias : 'mm_key',
keyPassword : 'pa123456',
]
]
}
除了上面方式自定义属性外,还可以在gradle.properties文件中定义,但只能是简单的Key-Value形式.
在gradle.properties文件中自定义如下属性:
// gradle.properties
TINKER_ENABLE=true
例如可以在settings.gradle文件中根据在gradle.properties文件中定义的属性做一些操作
if (hasProperty('TINKER_ENABLE') ? Boolean.parseBoolean(TINKER_ENABLE) : false) {
println "TINKER_ENABLE 打开了."
} else {
println "TINKER_ENABLE 关闭了."
}
// 当TINKER_ENABLE=true,输出日志信息
TINKER_ENABLE 打开了.
文件相关API
路径获取相关API
在Project中提供了很多获取文件路径的方法,如:getProjectDir(),getRootDir(),getBuildDir()
// Root project的根目录路径
println "the root directory of this project, ${project.getRootDir().absolutePath}"
// 当前project的build文件路径
println "the build directory of this project, ${project.getBuildDir().absolutePath}"
// 当前project的目录路径,如果当前project是Root project,等同于getRootDir()
println "The directory containing the project build file, ${project.getProjectDir().absolutePath}"
// 输出的日志信息
the root directory of this project, D:\work\yqb.com\newCode\merchantApp
the build directory of this project, D:\work\yqb.com\newCode\merchantApp\build
The directory containing the project build file, D:\work\yqb.com\newCode\merchantApp
文件操作相关API
文件的定位,根据文件路径获取文件内容
println getContent('settings.gradle')
def getContent(String path) {
try {
def file = file(path)
return file.text
} catch (Exception ex) {
println "getContent has error: ${ex.getMessage()}"
return ""
}
}
文件拷贝
Project为我们提供了简便的方法copy对文件进行拷贝。
def copyApk() {
this.copy {
// srcApkDir>>> D:\work\yqb.com\newCode\merchantApp\app\build\bakApk
// destApkDir>>> D:\work\yqb.com\newCode\merchantApp\build\apk
// from 用于指定拷贝的源文件或者文件夹
from file("${buildDir}/bakApk/")
// into 用于指定拷贝的目的地
into file("${getRootProject().getBuildDir().path}/apk")
}
}
除了使用from 和 into 指定源路径和目的地之外,还可以配置拷贝后使用rename文件重新命名、exclude移除不需拷贝的文件等。
def copyApk() {
this.copy {
// srcApkDir>>> D:\work\yqb.com\newCode\merchantApp\app\build\bakApk
// destApkDir>>> D:\work\yqb.com\newCode\merchantApp\build\apk
// 指定拷贝的源文件或者文件夹
from file("${buildDir}/bakApk/")
// 指定拷贝的目的地
into file("${getRootProject().getBuildDir().path}/apk")
// 移除不需要拷贝的文件, 例如:不拷贝以txt结尾的文件
//exclude "**/*.txt"
// 也可以使用闭包,移除不需要拷贝的文件
exclude { details ->
println "exclude>>> file: ${details.file}"
return details.file.name.endsWith('.txt')
}
// 重新命名拷贝的文件名
rename { String fileName ->
println "rename>> fileName: ${fileName}"
fileName.replace("app-arm-debug.apk", "test.apk")
}
}
}
文件树遍历
Project提供的fileTree方法,可以将指定文件目录下所有的文件封装成文件树对象操作
fileTree("build/outputs/apk") { ConfigurableFileTree fileTree ->
fileTree.visit { FileVisitDetails details ->
println "The file name is ${details.file}"
copy {
from details.file
into "${getRootProject().getBuildDir().path}/apk"
exclude { file ->
return file.file.isDirectory()
}
}
}
}
依赖相关API
Project提供了依赖相关的API,如 buildscript
buildscript {
repositories {
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.alibaba:arouter-register:1.0.2'
classpath("com.tencent.tinker:tinker-patch-gradle-plugin:${TINKER_VERSION}") {
changing = TINKER_VERSION?.endsWith("-SNAPSHOT")
exclude group: 'com.android.tools.build', module: 'gradle'
}
}
}
执行外部命令API
可以使用Project提供的javaexec 或者 exec 执行一个外部命令。使用外部命令实现一个copy功能
tasks.create(name: 'copyAPK') {
doLast {
def srcFilePath = this.buildDir.path + "/outputs/apk"
def destFilePath = this.buildDir.path + "/outputs/backup"
def command = "mv -f ${srcFilePath} ${destFilePath}"
exec { ExecSpec execSpec ->
try {
executable 'bash'
args '-c', command
} catch (Exception ex) {
println "copyAPK>>> error: ${ex}"
}
}
}
}
如果我的文章对您有帮助,不妨点个赞鼓励一下(^_^)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。