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