什么是 Gradle ?
所谓构建工具就是对你的项目进行编译、运行、签名、打包、依赖管理等一系列功能的合集,传统的构建工具有 Make、Ant、Maven、Ivy等,而 Gradle 是新一代的自动化构建工具。
上面说了,Gradle 是新一代的自动化构建工具,它是一个独立的项目,跟 AS、Android 无关,官方网站:https://gradle.org/, 类似 Ant、Maven这类构建工具都是基于 xml 来进行描述的,很臃肿,而 Gradle 采用的是一种叫做 Groovy 的语言,语法跟 Java 语法很像,但是是一种动态语言,而且在 Java 基础上做了不少改进,用起来更加简洁、灵活,而且 Gradle 完全兼容 Maven、Ivy,这点基本上宣布了 Maven、Ivy 可以被抛弃了,Gradle 的推出主要以 Java 应用为主,当然目前还支持 Android、C、C++。
Gradle 与 Android Studio 的关系
上面也提到,Gradle 跟 Android Studio 其实没有关系,但是 Gradle 官方还是很看重 Android 开发的,Google 在推出 AS 的时候选中了 Gradle 作为构建工具,为了支持 Gradle 能在 AS 上使用,Google 做了个 AS 的插件叫 Android Gradle Plugin ,所以我们能在 AS 上使用 Gradle 完全是因为这个插件的原因。在项目的根目录有个 build.gradle 文件,里面有这么一句代码:
classpath ‘com.android.tools.build:gradle:2.3.3’
这个就是依赖 gradle 插件的代码,后面的版本号代表的是 android gradle plugin 的版本,而不是 Gradle 的版本,这个是 Google 定的,跟 Gradle 官方没关系。
Gradle基本组件
每一个build.gradle文件代表着一个Project。Tasks在build.gradle中定义。当初始化构建进程时,gradle会基于build文件,集合所有的Project和Tasks,一个Tasks包含了一系列动作,然后它们将会按照顺序执行,一个动作就是一段被执行的代码,很像Java中的方法。
Project
每一个待编译的工程(可以是一个jar包,一个web应用,或者一个android app等)都称为一个Project。
Task
每一个Project在构建的时候都包含一系列的Task。一个Task其实就是构建过程中一个原子性的操作。比如一个Android APK的编译可能包含:Java源码编译Task、资源编译Task、JNI编译Task、lint检查Task、打包生成APK的Task、签名Task等。
Plugin
Gradle是一个框架,作为框架,它负责定义流程和规则。而具体的编译工作则是通过插件的方式来完成的。比如编译Java有Java插件,编译Groovy有Groovy插件,编译Android APP有Android APP插件,编译Android Library有Android Library插件。
简单来说,插件就是一系列任务的集合,主要作用是把一些重复利用的逻辑打包,这样就可以在不同的项目中可以重复的使用。
要使用插件,可以通过引入依赖的方式添加。
As如何依赖Gradle让Gradle作为自身的构建工具呢?
Google开发了一个Gradle插件,让As项目依赖这个插件,就相当于让Gradle作为自身的的构建工具。
现在比如我们新建一个As项目,打开项目的根目录的gradle.build文件。有如下代码:
buildscript {
repositories {
jcenter() //表示编译过程中依赖的仓库
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0' //依赖android开发使用的gradle插件
}
}
而要引入Android APP插件,就需要在build.gradle引用Android APP插件:
//申明使用插件,表明要编译的内容和产物
apply plugin: 'com.android.application'
//配置插件属性
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "zhj.gradledemo"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Android其实就是写了两个插件:com.android.application 和 com.android.library
应用这两个插件就可以实现Android APP和Android Library的构建。
.gradle文件夹
.gradle文件夹 是gradle 运行以后生成的缓存文件夹。
Project中的build.gradle文件
project下的build.gradle是基于整个project的配置,主要配置gradle 版本及全局依赖仓库、库或者其他全部参数。
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
//这里依赖的jcenter仓库是gradle脚本自身需要的资源
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
//这里依赖的jcenter仓库是项目所有模块需要的资源
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
module中build.gradle文件
//申明使用插件,表明要编译的内容和产物
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
//默认配置,会同时应用到debug和release版本上
defaultConfig {
applicationId "zhj.gradledemo"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true //是否混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //混淆文件的位置
}
debug {
minifyEnabled false
}
}
// 多渠道
productFlavors {
//可以设置不同渠道渠道号,应用名称
pro {
}
fre {
}
}
}
//依赖第三方库
dependencies {
//编译libs目录下所以jar包
compile fileTree(include: ['*.jar'], dir: 'libs') //导入所有的jar包
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
testCompile 'junit:junit:4.12'
proCompile 'com.android.support:recyclerview-v7:24.2.0'
}
Project中setting.gradle
这个文件是全局的项目配置文件,里面主要声明Project中所包括的所有module
//一个Project中所包括的所有module
include ':Gotobus', ':android-support-v7-appcompat'
include ':google-play-services_lib'
include ':TakeTours'
include ':Common'
include ':CompanyCommon'
Project中gradle.properties
//编译版本信息
APPLICATION_ID = com.jin.myAPP
COMPILE_SDK_VERSION = 23
BUILD_TOOLS_VERSION = 23.0.1
MIN_SDK_VERSION = 15
TARGET_SDK_VERSION = 1
VERSION_CODE = 1
VERSION_NAME = 1.0.0.0
//keystore信息
STORE_FILE = ../app/mykey.keystore
STORE_PASSWORD = your password
KEY_ALIAS = your alias
KEY_PASSWORD = your password
配置应用的签名信息
在android.signingConfigs{}下定义一个或者多个签名信息,然后在buildTypes{}配置使用即可。比如这里:
android {
signingConfigs {
release {
storeFile file("release.keystore")
keyAlias "release"
keyPassword "123456"
storePassword "123456"
}
debug {
...
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
debug {
signingConfig signingConfigs.debug
}
}
}
storeFile是签名证书文件,keyAlias是别名,keyPassword是key的密码,storePassword是证书的密码。配置好相关信息即可在buildTypes配置使用。
一般重要的信息,例如签名信息,可以直接将信息写到gradle.properties,然后在然后在build.gradle中引用即可。
buildTypes是指建构的类型,一般只用两种默认类型 debug 和 release ,顾名思义 debug 用来配置开发过程中的一些内容;release 用来配置正式发布版本的内容。有时我们需要发布介于debug与release之间的preview 版本。
Build Variant 差异管理
比如app生成不同版本(免费,收费),适配特殊机型,多渠道等需要发多个包,最终能编译出的apk的数量是由Product Flavor(产品种类)与Build Type(构建类型)决定的,
公式:Build Variant = Build Type x Product Flavor
BuildType(构建类型)
默认有debug和release两种,标示编译的类型,通常在混淆代码、可调式、资源压缩上做一些区分。
Product Flavor(产品种类)
为了满足“同一个project,根据一个很小的区分,来打不同的包”这个需求。实现多渠道打包。注意:这里的Flavor名如果是数字开头,必须用引号引起来。
调整module的目录结构sourceSets
默认情况下,java文件和resource文件分别在src/main/java和src/main/res目录下,在build.gradle文件的andorid{}里面添加下面的代码,便可以将java文件和resource文件放到src/java和src/resources目录下。
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
//设置java文件的位置
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
}
全局变量定义及引用
可以在顶层build.gradle脚本中定义一些全局变量,提供给子脚本引用
ext {
// global variables definition
compileSdkVersion = 'Google Inc.:Google APIs:23'
buildToolsVersion = "23.0.3"
minSdkVersion = 14
targetSdkVersion = 23
}
子脚本引用
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}
}