在Java的世界里Ant,Maven,Gradle为三大常用的构建利器。在Gradle诞生之前构建工具一直都是Ant,之后进化到Maven。Ant、Maven主要使用XML配置编译规则,对程序员而言最方便的当然是以编程的方式来配置规则。而Gradle就这样被历史选中了,集Anit、Maven优点于一身,同时具备脚本语言的特性,相信你在使用之后一定会拍手惊呼道“太方便,太方便”。

Groovy

Groovy是一门动态语言,同Java一样运行在JVM上,Groovy的语法与Java很相似,两者可以混合编程,而同样的任务使用相比Java所需的代码更少。Gradle选择Groovy来作为构建语言,是因为它给Java开发人员提供了迄今为止最大的透明度。

基本语法

详细的语法介绍参见官方文档,本文只作简单介绍。

  • 注释同java相同,分单行注释、多行注释、文档注释。
  • Groovy中变量及类默认public。
  • Groovy支持动态类型,使用def定义变量,当然也可省略def,语句结尾的分号也能省略。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //定义变量
    int var=1
    def var='Hello World'
    def int var=2
    //定义方法,可以不声明返回值类型,最后一行代码为方法返回值
    def function(){
    string
    }
    //参数类型可以不指定
    def function(arg1,arg2){
    }
    //指定返回值类型
    String function(){
    return 'string'
    }
  • String字符串

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //单引号
    def value='a single quoted string'
    def name='Troy'
    //双引号会对$进行求值
    def greeting="Hello ${name}"//输出Hello Troy
    //三引号,表示字符串换行
    def multiline='''
    line one
    line two
    line three
    '''
  • 集合

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //Lists
    def numbers = [1, 2, 3]
    //List中可以存放任意类型
    def heterogeneous = [1, "a", true]
    //添加元素
    numbers.add(4)
    numbers << 5
    numbers[1] = 3
    //输出
    println numbers[1]

    //Maps
    //map使用key value方式声明
    def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
    //添加元素
    colors.put(yellow:'#FFFF00')
    colors << [yellow:'#FFFF00']
    //输出red颜色
    println colors['red']
    //或者
    println colors.green
  • 闭包,闭包是一段可以执行的代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //闭包语法格式
    { [closureParameters -> ] statements }
    //使用花括号把代码括起来
    { item++ }
    //->前面为参数默认为it,相当于java中this,->后面为代码
    { -> item++ }
    { it -> println it }
    { String x, int y ->
    println "hey ${x} the value is ${y}"
    }
    //使用闭包作为数据类型
    def listener = { e -> println "Clicked on $e.source" }
    //调用闭包
    listener.call('call')
    //或者
    listener('call')

Gradle

Gradle可以说是一个框架,定义了流程和规则,而且具体的编译工作则由插件来完成。比如常见的Java插件、Android插件。每个插件中又定义了各种task。

Gradle基本概念

projects (项目)

我们的Android Application、Android Library、Java Library都是单个的Project,可以说每个待编译的工程都是一个Project。
以某项目为例,该项目总共有几个Project呢?答案是3个!
分别是appscrollanimationlibrarysocial_sdk_library_project。从目录结构我们可以看出每个Project对应一个build.gradle文件,该文件定义了Project的编译规则。根目录下build.gradle用于配置子Project,settings.gradle文件声明包括多少个子Project,整体上这就是一个MultiProject。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
├── app
│   ├── build.gradle
│   ├── libs
│   ├── proguard-rules.pro
│   ├── settings.gradle
│   └── src
├── build.gradle
├── gradle
│   └── wrapper
├── gradle.properties
├── gradlew
├── gradlew.bat
├── scrollanimationlibrary
│   ├── build.gradle
│   └── src
├── settings.gradle
└── social_sdk_library_project
├── AndroidManifest.xml
├── build.gradle
├── gradle
├── libs
├── proguard-project.txt
├── project.properties
└── res

使用projects命令查看project

1
2
3
4
5
6
7
8
------------------------------------------------------------
Root project
------------------------------------------------------------

Root project 'Coding-Android'
+--- Project ':app'
+--- Project ':scrollanimationlibrary'
\--- Project ':social_sdk_library_project'

task (任务)

一个task代表更细化的构建,可能是编译一些 classes, 创建一个 JAR, 生成 javadoc, 或者生成某个目录的压缩文件。
查看Project包含的任务可以使用task命令,查看具体某个Project的任务使用project-name:task命令,如app:task,执行某个task使用task-name,如assemble

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Parallel execution with configuration on demand is an incubating feature.
Incremental java compilation is an incubating feature.
:app:tasks

------------------------------------------------------------
All tasks runnable from project :app
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for each variant.
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assembles all variants of all applications and secondary packages.
assembleAndroidTest - Assembles all the Test applications.
assembleDebug - Assembles all Debug builds.
assembleRelease - Assembles all Release builds.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
clean - Deletes the build directory.
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources
mockableAndroidJar - Creates a version of android.jar that's suitable for unit tests.
..............

创建任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//普通写法
task hello {
doLast{
//运行阶段执行
println 'Hello world!'
}
}

//更简洁的写法
task hello <<{
//运行阶段执行
println 'Hello world!'
}

//另一个种写法
task hello {
//配置阶段执行
println 'Hello world!'
}

Gradle生命周期
  • 初始化阶段,读取settings.gradle,决定了本次构建过程包含的子Project。
  • 配置阶段,解析子Project的中build.gradle,创建所需的task。
  • 运行阶段,执行相关task。
Gradle配置讲解

从API的角度来理解,Gradle有三种对象,每种对象对应不同的脚本文件。

  • Gradle对象,对应着Gradle。如我们执行的某个命令./gradlew task
  • Project对象,对应build.gradle。
  • Settings对象,对应settings.gradle。

settings.gradle

1
2
//指定包含的子project
include ':app', ':social_sdk_library_project', ':scrollanimationlibrary'

MultiProject build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//全局配置
buildscript { //Script Block
repositories { //Script Block
//依赖的仓库
jcenter()
}
dependencies { //Script Block
//依赖的插件对应的class path
classpath 'com.android.tools.build:gradle:2.2.2'
}
}

//配置所有子project
allprojects {
repositories {
jcenter()
//私有库地址
maven { url "http://172.16.1.19:8081/repository/maven-releases/" }
}
}

Project build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Android 插件
apply plugin: 'com.android.application'
//Android Plugin DSL Reference
//http://google.github.io/android-gradle-dsl/current/
android {
compileSdkVersion 21
buildToolsVersion "23.0.2"

defaultConfig {
applicationId "net.coding.program"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

//依赖相关
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:21.0.+'
compile 'com.android.support:appcompat-v7:21.0.+'
}

指定.so库

1
2
3
4
5
6
7
android{
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}

配置apk签名

1
2
3
4
5
6
7
8
9
10
11
12
13
android{
signingConfigs {
debug {

}
release {
storeFile file("../demo.keystore")
storePassword "123456"
keyAlias "demo"
keyPassword "123456"
}
}
}

构建不同类型的版本
通过添加applicationIdSuffix ".debug"修改包名,可以使内测版与正式版同时安装在手机上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
android {
buildTypes {
debug {
minifyEnabled false
zipAlignEnabled false
shrinkResources false
signingConfig signingConfigs.debug
//修改包名,添加.debug后缀
applicationIdSuffix ".debug"
debuggable true
}

release {
minifyEnabled true
zipAlignEnabled true
shrinkResources false
debuggable false
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

多渠道打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//在AndroidManifest.xml里配置PlaceHolder
<meta-data
android:name="UMENG_CHANNEL"
android:value="channel_value" />

// 多渠道打包配置
productFlavors {
yingyongbao {
manifestPlaceholders = [channel_value: "yingyongbao"]
}
"360" {
manifestPlaceholders = [channel_value: "360"]
}
}

//打包命令
./gradlew assembleYingyongbao //应用包渠道
./gradlew assembleRelease //全部渠道

引用其它gradle配置

1
apply from: '../tinker-patch.gradle'

扩展属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//root project build.gradle配置ext属性
ext {
compileSdkVersion = 21
buildToolsVersion = "23.0.2"
minSdkVersion = 21
targetSdkVersion = 21
versionCode = 100
versionName = "1.0.0"
}

//子project build.gradle使用ext属性
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
}

BuildConfig

1
2
3
4
5
6
7
8
9
10
//gradle 中定义BuildConfig字段
android {
defaultConfig {
buildConfigField("String", "PATCH_VERSION", "\"1\"")
buildConfigField("boolean", "DEBUG", "true")
}

//在程序中获取
String patchVersion=BuildConfig.PATCH_VERSION;
boolean debug=BuildConfig.DEBUG;

参考资料