Gradle核心(二):Gradle Project详解及实战

博客主页java

在讲解Task以前,先了解Gradle核心之Project详解及实战android

Project相关的API

获取Project

查看全部的Project,在Gradle中为咱们提供了Task任务projects,执行下面命令后,会列出全部的Projectsegmentfault

> gradlew projects

// 执行上面命令后,列出全部的project,包括Root project
------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'walletApp'
\--- Project ':app

咱们能够经过Project提供的API访问全部的project。getAllprojects返回全部的project,包括当前project,返回类型:Set集合bash

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 projectRoot project ,对应的方法分别是getParent()getRootProject()。他们主要区别是,getParent()若是自己就是Root Project,则返回null;而getRootProject()若是自己就是Root Project,返回Root project,不会返回nullapp

/**
 * 获取父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版本、依赖等信息maven

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统一配置gradle

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了。
ui

除了Project默认提供的,咱们也能够经过ext关键字自定义属性。下面是咱们自定义的应用包名、版本信息、依赖、签名文件等相关信息。this

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")
    }
}

除了使用frominto 指定源路径和目的地以外,还能够配置拷贝后使用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}"
            }
        }
    }
}

若是个人文章对您有帮助,不妨点个赞鼓励一下(^_^)

相关文章
相关标签/搜索