Gradle之Project Api 使用
- 2019 年 12 月 26 日
- 筆記
Project Api使用
命令使用
- 在
Android studio
命令行中输入./gradlew clean
进行工程的清理 - 输入
./gradlew build
进行task任务的构建 - 输入
./gradlew projects
列表展示当前根project
与它的子project
Gradle 生命周期:
- 在初始化阶段完成所有的配置操作
- 初始化阶段后就是配置阶段,
- 再之后就是执行阶段,也就执行task中的内容
四个不同阶段的配置监听
beforeEvaluate
:配置开始前的监听回调afterEvaluate
:配置阶段完成以后的监听回调gradle.buildFinished
:gradle 执行完毕的监听回调setting.gradle
是每个gradle开始的入口,即初始化阶段
/** * 配置阶段开始前的监听回调 */ this.beforeEvaluate {} /** * 配置阶段完成以后的监听回调 */ this.afterEvaluate { println '配置阶段执行完毕' } /** * gradle 执行完毕的回调监听 */ this.gradle.buildFinished { println '执行阶段执行完毕' }
Project 相关api
getAllprojects
:获取根project与其他projectgetSubprojects
:获取当前project以及所有子projectgetParent
:获取当前父project,如果当前工程没有父project 就返回nullgetRootProject
:也是获取根project ,不过当前方法可以在任意地方使用,即使当前project之上已经没有根project,Project 是以树的形式,而树一定会有根节点,而parent已经是树节点就没有根节点allprojects
:对所有的过程进行配置,当前根project与它以下子projectsubprojects
:不包括当前根工程,只包括子工程,添加公共配置
/** * Project 相关api * 执行在配置阶段 */ this.getProjects() def getProjects(){ println '------' println 'Root Project' println '------' //输出根project与其他project this.getAllprojects().eachWithIndex{ Project project, int index-> if(index==0){ println "Root Project = ${project.name}" }else { println "+-- project = ${project.name}" } } println 'Sub Project' //获取当前project的所有子project this.getSubprojects().eachWithIndex{ Project project, int i -> println "+-- project = ${project.name}" } } this.getParentProject() /** * 获取父project 如果当前project没有父project就会报错显示null * @return */ def getParentProject(){ def name = this.getParent().name println "the parent project name is $name" } /** * 也是获取根project ,不过当前方法可以在任意地方使用,即使当前project之上已经没有根project * Project 是以树的形式,而树一定会有根节点,而parent已经是树节点就没有根节点 */ this.getRootPro() def getRootPro(){ def name = this.getRootProject().name println "the root project name is $name" }
setting.gradle
是每个gradle开始的入口,即初始化阶段
println '初始化阶段开始执行'
/** * 这是一个project,也就是内部方法都可以调用 */ project('app'){Project project-> // println "the name is ${project.name}" apply plugin: 'com.android.application' group 'com.yif' version '1.0.0-alpha' dependencies { } android{ } }
/** * 对所有的过程进行配置,当前根project与它以下子project */ allprojects { group 'com.yif' version '1.0.0-alpha' } println project('app').group /** * 不包括当前根工程,只包括子工程,添加公共配置 */ subprojects {Project project -> //判断当前工程是否是子工程,从而引入外部的maven功能 if(project.plugins.hasPlugin('com.android.library')){ apply from:'../publishToMavean.gradle' } }
属性相关Api
在根工程下自定义config.gradle
可以直接在根project引用apply from:'config.gradle'
如果需要在app project
中引用,需要加rootProject
,表明当前gradle路径在根工程下,apply from: this.rootProject.file('releaseinfo.gradle')
//ext 加{}闭包是扩展属性 ext { build_version = [ compileSdkVersion: 28, buildToolsVersion: '29.0.0', minSdkVersion : 15, targetSdkVersion : 29, versionCode : 1, versionName : '1.0' ] supportDeps = [ appcompat : [group: 'androidx.appcompat', name: 'appcompat', version: '1.0.0-beta01'], core_ktx : [group: 'androidx.core', name: 'core-ktx', version: '1.2.0-alpha04'], constraintlayout: [group: 'androidx.constraintlayout', name: 'constraintlayout', version: '1.1.3'] ] testDeps = [ junit : [group: 'junit', name: 'junit', version: '4.12'], runner : [group: 'androidx.test', name: 'runner', version: '1.1.0-alpha4'], espresso: [group: 'androidx.test.espresso', name: 'espresso-core', version: '3.1.0-alpha4'] ] commonDeps = [ "coroutines_core" : 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0', "coroutines_android": 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.0' ] } 然后在project的build.gradle通过apply from: this.file('config.gradle')进行引入 /** * 使用subProject定义所以子工程的公共属性 */ //subprojects { // ext{ // compileSdkVersion = 28 // buildToolsVersion = '29.0.0' // } //} /** * 或者直接在根工程中定义,通过rootProject进行调用 */ ext{ compileSdkVersion = 28 buildToolsVersion = '29.0.0' } android { //也可以不用使用rootProject 因为gradle进行规定根project定义的属性,子project可以直接调用,是一种继承关系,无需使用rootProject // compileSdkVersion this.rootProject.compileSdkVersion compileSdkVersion this.compileSdkVersion buildToolsVersion this.buildToolsVersion defaultConfig { applicationId "com.example.kotlinproject" minSdkVersion build_version.minSdkVersion targetSdkVersion build_version.targetSdkVersion versionCode build_version.versionCode versionName build_version.versionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } }
在 gradle.properties
中定义扩展属性,只能定义key与value
类型属性,无法定义闭包
里面定义isLoadApp = true
,在setting.gradle
进行配置是否引入app project
//判断是否设置isLoadApp属性,设置了为false就不进行引入 if(hasProperty('isLoadApp')? isLoadApp.toBoolean():false){ include ':app' }
也可以在里面定义mCompileSdkVersion = 28
,然后引入 compileSdkVersion mCompileSdkVersion.toInteger()
文件属性操作
文件定位
getRootDir().absolutePath
:获取根工程的绝对路径getBuildDir().absolutePath
:获取工程下Build文件绝对路径getProjectDir().absolutePath
:获取当前工程的绝对路径
//获取根工程的绝对路径 println "the root path is " +getRootDir().absolutePath //获取工程下Build文件绝对路径 println "the build path is "+getBuildDir().absolutePath //获取当前工程的绝对路径 println "the project file is "+getProjectDir().absolutePath println getContent('config.gradle') /** * 文件定位 * 获取路径下所以文本内容 * @param path * @return */ def getContent(String path){ try{ def file = file(path) //相对于当前工程进行查找 return file.text }catch(GradleException e){ e.printStackTrace() println 'file not find' } return null }
文件拷贝
使用copy闭包方法,from file 从哪个文件开始拷贝,into到哪个目录文件中去
/** * 文件拷贝,将当前文件拷贝到build文件夹下 */ copy{ from file('proguard-rules.pro') into getRootProject().getBuildDir() } /** * 文件夹的拷贝,只支持在同一个根工程下操作 */ copy{ from file('build/outputs/apk/') into getRootProject().getBuildDir().path + "/apk" //文件拷贝进行排除操作 exclude {} //文件重命名 rename {} }
文件遍历
使用的是fileTree闭包方法
/** * 对文件树进行遍历 */ fileTree('build/outputs/apk'){FileTree fileTree-> fileTree.visit {FileTreeElement fileTreeElement-> println "the file name is $fileTreeElement.name" //在将当前文件下的文件拷贝到根工程build下的test文件夹下 copy{ from fileTreeElement.file into getRootProject().getBuildDir().path + "/test/" } } }
依赖api
在根工程下存在buildscript
构建脚本,内部有两个闭包方法,分别是:
repositories
:配置我们的仓库地址,闭包内部属性是RepositoryHandler
dependencies
:配置工程插件依赖的地址,gradle本身需要引入的第三方库
/** * 依赖api */ buildscript {ScriptHandler scriptHandler -> //配置我们的仓库地址 scriptHandler.repositories{RepositoryHandler repositoryHandler-> repositoryHandler.jcenter() repositoryHandler.mavenCentral() repositoryHandler.mavenLocal() repositoryHandler.google() repositoryHandler.maven { name 'personal' url 'https://localhost:8081//repository' //地址需要用户名与密码 credentials{ username = 'yif' password = '123456' } } } //配置工程插件依赖地址 scriptHandler.dependencies { //gradle本身需要引入第三方库 classpath 'com.android.tools.build:gradle:3.3.2' } } app的build.gradle //应用程序所需要的第三方库 dependencies { //添加文件树或者文件夹的依赖fileTree,文件依赖file,多个文件files implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation supportDeps.appcompat implementation supportDeps.core_ktx implementation supportDeps.constraintlayout implementation commonDeps.coroutines_core implementation commonDeps.coroutines_android implementation 'androidx.appcompat:appcompat:1.0.0-beta01' //库冲突通过exclude排除依赖 implementation 'androidx.constraintlayout:constraintlayout:1.1.3'{ exclude module : 'support-v4' exclude group : 'com.android.support' transitive false//禁止传递依赖false 可以进行传递依赖true } testImplementation testDeps.junit androidTestImplementation testDeps.runner androidTestImplementation testDeps.espresso }
传递依赖
比如:工程A依赖于工程B,工程B依赖于工程C,工程A传递依赖于工程C,不能进行传递依赖,是不确定的,可能B升级后就不需要依赖于C,那么A不会在C找到所需东西
Gradle 执行外部命令进行拷贝文件到磁盘下
/** * 文件拷贝到外部电脑文件夹下 */ task(name:'apkcopy'){ doLast{ //gradle 执行阶段去执行 def sourcePath = this.buildDir.path + '/outputs/apk' def destinationPath= '/Users/zhangtianzhu/Downloads/' def command = "mv -f ${sourcePath} ${destinationPath}" exec { try{ executable 'bash' args '-c',command println 'the command is execute success' }catch(GradleException e){ println 'the command is execute failed' } } } }