前言
Android 开发目前大家使用的IDE是Android Studio,所以和Gradle打交道就是必不可少的了。
大部分时间可能我们关注的都是业务代码的开发,然而了解gradle可以帮助我们更好的构建我们的项目
关于Gradle
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言来声明项目设置,而不是传统的XML
这是维基百科上对Gradle的描述,可以了解到:
- gradle 是个构建工具,不是一种语音。
gradle 构建使用到是 Groovy 语言。
Android项目中gradle配置
Android 工程中gradle配置文件有build.gradle
、settings.gradle
、gradle-wrapper
等如下图:
settings.gradle
: 工程配置,多projrct项目中配置项目结构。settings.gradle
配置文件在主工程中,文件中可以查看其他的配置projectbuild.gradle
:project工程配置文件,配置工程依赖编译等信息
tip:
- 单project项目,只要一个
build.gradle
文件就OK了。 多projec项目需要由settings.gradle
来配置多个build.gradle
- 查找
settings.gradle
的顺序是:当前目录 -> 兄弟目录 master -> ⽗目录
// `settings.gradle` 配置文件
include ':app'
rootProject.name='Demo'
根目录下到gradle配置(Project: Demo)如下(配置的用途见注释):
代码语言:javascript复制// 主项目中build.gradle 配置文件
buildscript {
ext.kotlin_version = '1.3.61'
repositories {
// 这里配置的是 下面 dependencies中配置的依赖的仓库地址
google()
jcenter()
}
dependencies {
// 这里的引入的依赖, 是为了使用 gradle 和 kotlin 的 plugin。
// 例如: apply plugin: 'com.android.application' , apply plugin: 'kotlin-android'
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
// 针对项目的仓库配置 , 每一个model 都使用这个仓库
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
app model 中build.gradle配置如下(用途见注释)
代码语言:javascript复制// 这里使用的 plugin ,需要在根目录下的gradle中配置引用
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.tencent.demo"
minSdkVersion 17
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
// buildType 默认有 debug 和 release 两个, 也可以进行自定义扩充
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
// compile : 已经被废弃
// api: 是 compile 的替代用法, 会传递依赖
// implementation : 不传递依赖。
// 传递依赖时,二级项目的改动会导致0级项目的重新编译; 不传递依赖时二级项目的改动不会导致0级项目的重新编译
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
tips:
buildTypes
和 Flavor
的用法可以参考 Android 构建多APK
gradle 执行阶段分析
- 初始化阶段:执⾏ settings.gradle,确定主 project 和子 project
- 定义阶段: 执行每个 project 的 bulid.gradle,确定出所有 task 所组成的有向无环图
- 执⾏阶段:按照上一阶段所确定出的有向⽆环图来执⾏指定的 task
gradle task 介绍
task 的写法如下:
代码语言:javascript复制task test() {
print('初始化代码')
doFirst {
print('doFirst')
}
doLast {
print('doLast')
}
}
/*
* 1. doFirst() 和 doLast() 在 task 执行过程中被执⾏,在执行阶段(第三阶段)执行,如果用户没有直接或者间接执行task,那这部分的代码块就不会执行
* 2. 初始化代码,在task创建的时候就会被执行,是在定义阶段(第二阶段)执行
* 3. doFirst() 是插入在队列的前面,doLast()是插入到队列的后面
*/
task clean(type: Delete) {
delete rootProject.buildDir
// tasks["nameA"].dependsOn nameB
}
/*
* 1. task 可以使用 task taskA(dependsOn: b) 的形式来指定依赖。
* 2. tasks["nameA"].dependsOn nameB 也可以使用这种方式指定依赖关系
* 3. 指定依赖后,task 会在⾃己执⾏前先执⾏⾃己依赖的 task
*/
android 中可以使用如下命令执行task
代码语言:javascript复制 $ ./gradlew assembleDebug
BUILD SUCCESSFUL in 5s
25 actionable tasks: 3 executed, 22 up-to-date
- 在第一二之间插入相关修改
// 修改写入settings.gradle 最后。
- 在第二三之间插入相关修改
afterEvaluate {
// 插⼊入代码
}
例如修改apk名称:
app build.gradle 种写法:
android.applicationVariants.all {
variant ->
variant.outputs.all {
//在这里修改apk文件名
outputFileName = "${variant.name}-v${variant.versionName}.apk"
}
}
// 自定义文件种实现方法
project.afterEvaluate {
android.applicationVariants.all { variant ->
variant.outputs.all { output ->
def buildNoSuffix = System.env.BuildNo ? ".${System.env.BuildNo}" : ".0"
//重命名为
def releaseApkName = "${variant.name.capitalize()}_${variant.mergedFlavor.versionName}${buildNoSuffix}.apk"
println "releaseApkName: " releaseApkName ", buildNoSuffix:" buildNoSuffix
outputFileName = releaseApkName
}
}
}