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與其他project
  • getSubprojects:獲取當前project以及所有子project
  • getParent:獲取當前父project,如果當前工程沒有父project 就返回null
  • getRootProject:也是獲取根project ,不過當前方法可以在任意地方使用,即使當前project之上已經沒有根project,Project 是以樹的形式,而樹一定會有根節點,而parent已經是樹節點就沒有根節點
  • allprojects:對所有的過程進行配置,當前根project與它以下子project
  • subprojects:不包括當前根工程,只包括子工程,添加公共配置
/**      * 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'              }          }      }  }