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' } } } }