我们在上篇文章《Android Gradle使用详解(一) 之 Gradle基础》中介绍了一些关于Gradle的入门相关知识点。本文中会在此基础上对Android工程中Gradle的相关知识进行进一步学习。
1 项目结构
我们在通过Android Studio创建一个APP工程时,目录结构如下:
可以看到工程目录中会自动生成一些文件。其中可以看到一些我们熟悉的文件,因为它们跟我们在上篇文章中的Hello World生成的是一样的。有.gradle文件夹、gradle文件夹、build.gradle文件、gradlew文件、 gradlew.bat文件 以及未见过的Settings文件。我们现在就来一步步分析Android Studio创建工程后Gradld的相关知识点。
1.1 Settings文件
在Gradle中,根目录定义了一个设置文件Settings,它是用于初始化以及工程树的配置文件。简单说就是为了配置工程的子工程,在Android Studio中就是配置Project和Module。可以看到,我们在刚新建的APP工程New Project后Settings文件只是简单的一行代码:
include ':app'
若再执行New Model后,Settings文件会自动变成这样:
include ':app', ':mylibrary'
所以,一个子工程只有在Settings文件里配置了Gradle才会识别,才会在构建的时候被包含进去。新建的Model默认是放在跟Project放在根目录中,倘若需要更改存放位置于根目录的sub-project文件平下,也是很简单,还是更改一下Settings文件即可,例如:
include ':app', ':mylibrary'
project(':mylibrary').projectDir = new File('sub-project/mylibrary')
或者(此方式会在左边Project面板中多出一项sub-project的空的model)
include ':app'
include ':sub-project:mylibrary'
1.2 Build文件
每个Project都会有一个Build文件,它是Project构建的入口,正如上篇文章中的Hello World示例一样。在Android Studio工程中,若存像上述中有app和mylibrary两个子工程的话,则会出现3个Build文件,它们分别是Root Project的build.gradle和两个Child Project的build.gradle。其中Root Project的build.gradle文件可以对Child Project统一配置,比如应用的插件、依赖的jcenter库等。例如在Root Project的build.gradle文件有这样的配置代码:
allprojects {
repositories {
google()
jcenter()
}
}
也有存在在Root Project的build.gradle中使用subprojects的情况。allprojects和subprojects的区别在于,allprojects是所有模块配置,包括自己,而subprojects只是对Child Project的配置。
2 插件简介
Gradle本身内置了很多常用的插件像Java插件,Android Gradle插件就是基于内置的Java插件实现的。插件分二进制插件和脚本插件。使用插件前要先通过Project.apply()方法来应用它。
2.1 二进制插件
二进制插件就是实现了org.gradle.api.Plugin接口的插件,它们可以有plugin id,例如应用一个java插件:
apply plugin: 'java'
其中,’java’是Java插件的plugin id,它是唯一的。又例如应用android插件,可以看到Child Project的build.gradle文件第一行是:
apply plugin: 'com.android.application'
2.2 应用脚本插件
应用脚本插件,其实就是把这个脚本加载进来,它使用的是关键字from,后面紧跟的是一个脚本文件,可以是本地的,也可以是网络的,如果是网络上的话要使用HTTP URL。示例:
build.gradle
apply from:'version.gradle'
task hello << {
println "APP version: ${versionName},code:${versionCode}"
}
version.gradle
ext {
versionName = '1.0.0'
versionCode = 100
}
示例中我们把APP的版本号和版本名称单独放在一个脚本文件里。这样我们以后每次APP发版本只需要更改version.gradle文件即可。
2.3 第三方插件
若是第三方发布的作为jar的二进制插件,我们在应用时,必须要先在buildscript{}里配置其classpath才能使用。这个就好比Android Gradle插件,它是属于第三方插件,它托管在Jcenter上,所以我们可以看到在Root Project的build.gradle文件发现有这样的配置代码:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
buildscript{}块是一个在构建项目之前是,为项目进行前期准备和初始化相关配置依赖的地方,配置好所需的依赖后,就可以在Child Project的build.gradle中应用插件,如可见\app\build.gradle中的第一行代码:
apply plugin: 'com.android.application'
3 Java插件
Android Gradle插件是基于内置的Java插件来实现的第三方插件,所以我们在开始学习Android Gradle插件前,先来了解Java插件。Java插件约定了项目结构,只有我们遵循这些约定,Java插件才能找到我们的Java类、资源进行编译、单元测试类等。默认情况下:
src/main/java 源代码存放目录
src/main/resources 打包资源文件存放目录
src/test/java 单元测试用例存放目录
src/test/resources 单元测试中使用的文件
3.1 约定的项目结构
main和test是Java插件内置的两个源代码集合,如果想自己添加一个如vip的目录可以在build脚本里这么配置:
apply plugin: ‘java’
sourceSets {
vip {
}
}
添加一个vip的源代码集合后,我们就可以在src下新建vip/java和vip/resurces目录来存放vip相关的源代码和资源文件。当然默认的文件目录其实也可以修改的,例如:
sourceSets {
vip {
java {
srcDirs ‘src/vip2/java’
}
resources.srcDirs = [‘src/ vip2/resources’] // 另外一样配置写法
}
}
如果要修改main和test两个内置的两个源代码集合的存放目录也是可以的,按照上面vip一样,将其配置一下就可以。
除此之外,SourceSet里的源集属性有:
属性名 | 类型 | 描述 |
name | String | 它是只读,比如main |
output.classesDir | File | 该源集编译后的class文件目录 |
output.resourcesDir | File | 编译后生成的资源目录 |
compileClasspath | FileCollection | 编译后源集时所需的classpath |
java | SourceDirectorySet | 该源集的Java源文件 |
java.srcDirs | Set | 该源集的Java源文件所在目录 |
resources | SourceDirectorySet | 该源集的资源文件 |
resources.srcDirs | Set | 该源集的资源文件所在目录 |
3.2 配置第三方依赖
我们在开发过程中,不可避免会依赖很多优秀的开源第三方Jar。要想使用这些第三方依赖,就要提前告诉给Gradle配置好如何找到这些依赖。例如上述提到Android Gradle是第三方插件,在使用前必须在repositories中进行配置,告诉Gradle是要去jcenter库搜寻。
repositories
repositories {
jcenter()
}
除jcenter库以外,如若需要引用其它插件或Jar,我们也可以从mavenCentral、ivy、google或者自己搭建的Maven私服库等中搜寻,例如:
repositories {
jcenter()
maven {
url ‘http://www.xxx.com/’
}
}
dependencies
配置好仓库后,就可以继续配置依赖了。还是例如上述提到Android Gradle是第三方插件,在repositories配置后就可使用dependencies来进行依赖配置:
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
//classpath group: 'com.android.tools.build', name: 'gradle', version: '3.0.1'
}
除了classpath,还提供了以下的依赖配置:
implementation ( 原 compile) 编译时依赖,依赖不可传递
api ( 原 compile) 编译时依赖,依赖可传递
compileOnly ( 原 provided) 编译时依赖,但代码不能打进包中
runtime 运行时依赖
testImplementation 编译测试用例时依赖,依赖不可传递
testApi 编译测试用例时依赖,依赖可传递
testRuntime 仅仅在测试用例运行时依赖
archives 项目发布构件(JAR包等)依赖
default 默认依赖配置
3.3 依赖另一个Gradle项目
在项目内部中当Child Project里的app要依赖另一个module时,一般就会在app的build.gradle文件中加入以下的配置:
dependencies {
compile project(':mylibrary')
}
如果依赖的是Jar包,则可以这样:
dependencies {
compile files( ‘libs/test.jar’, ‘libs/test2.jar’ )
}
或者可以依赖整个文件夹下的所有Jar包:
dependencies {
compile fileTree( dir : ‘libs’, include : ‘*.jar’ )
}
在Android Studio 3.0开始推荐使用implementation取代了compile。它们的区别是implementation是依赖关系不可能传递,而compile可以。使用implementation可以降低项目依赖的偶合性和提高安全性。例如,项目中有app、module1、module2三个module,它们的依赖关系是这样:app依赖module1,module1依赖module2,如果是使用compile依赖的话是可以做到依赖传递,但是如果使用implementation的话,依赖传递就会失效。
3.4 任务
Java插件为我们内置了很多有用的Task,下面列举一些通用的任务:
任务名称 | 类型 | 描述 |
compileJava | JavaCompile | 使用javac编译Java源文件 |
processResource | Copy | 把资源文件拷贝到生成的资源文件目录里 |
classes | Task | 组装产生的类和资源文件目录 |
compileTestJava | JavaCompile | 使用javac编译Java源文件 |
processTestResources | Copy | 把测试资源文件复制到生产的资源文件目录里 |
testClasses | Task | 组装产生的测试类和相关资源文件目录 |
jar | Jar | 组装Jar文件 |
Javadoc | Javadoc | 使用javadoc生成Java API文档 |
test | Test | 使用Junit或TestNG运行单元测试 |
uploadArchives | Upload | 上传包含Jar的构建,用archives{}闭包配置 |
clean | Delete | 清理构建生成的目录文件 |
cleanTaskName | Delete | 删除指写任务生成的文件,比如cleanJar删除Jar任务生成的 |
我们在使用Android Studio新建工程后,便能在Root Project的build.gradle中的最后看到clean任务的配置:
task clean(type: Delete) {
delete rootProject.buildDir
}
对于内置的main和test源集 或者 自己新增的源集(像上面示例的vip)也有一些源集任务:
任务名称 | 类型 | 描述 |
compileXXJava | JavaCompile | 使用javac编译指写源集的Java源代码 |
processXXResources | Copy | 把指写源集的资源文件复制到生产文件下的资源目录中 |
XXClasses | Task | 组装给指写源集的类和资源文件目录 |
3.5 属性
Java插件为我们也内置了很多有用的属性,这些属性都被添加到Project中,可以直接使用,比如前面提到的sourceSets,下面列举一些常用的源集属性:
属性名 | 类型 | 描述 |
sourceSets | SourceSetContainer | 该Java项目的源集,可以访问和配置源集 |
sourceCompatibility | JavaVersion | 编译Java源文件使用的Java版本 |
targetCompatibility | JavaVersion | 编译生成的类的Java版本 |
archivesBasenName | String | 打包成Jar或Zip文件的名字 |
manifest | Manifest | 用于访问或配置manifest清单文件 |
libsDir | File | 存放生成的类库目录 |
distsDir | File | 存放生成的发布的文件的目录 |