一.基础概念
Gradle 有约定优于配置的原则,即为设置和属性提供默认值。
Gradle 是基于 Groovy 领域专用语言 DSL.
在 Gradle 中,最重要的两个概念是项目和任务。每一次构建都包括至少一个项目,每一个项目又包括多个任务。每个 build.gradle 文件都代表着一个项目,任务定义在构建脚步里。
源集 source set
一 个源集是一组源文件,它们会一起执行和编译。
在 Android 中,main 就是一个源集。
二. 常用命令
./gradlew assemble 生成 releas 和 debug 版本, 如果是配置了多渠道,则每个渠道都会生成 Release 和 Debug 版本
./gradlew assembleRelease 则会为每个渠道生成 Release 包, ./gradlew assembleDebug 类似
// 可以指定渠道版本
./gradlew assembleXiaomiDebug
运行测试,遇到问题会立即停止
./gradlew test
如果是想运行特点的 flavor
./gradlew testXiaomiDebug , 例子
// 如果遇到问题,还想继续执行
./gradlew test -continue
只针对一个特定的测试类, 例子
./gradlew testDebug –test=”*.LogicTest”
MyApp
|
|—- build.gradle
|—- settings.gradle
|
—- app
|
— build.gradle
例子
1. settings.gradle
settings 在初始化阶段被执行,定义包含的模块。
例如这包含 app 和 mylibrary
![这里写图片描述](https://img-blog.csdn.net/20170527221558196?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXhodWFuZzIwMDg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
2. 顶层构建文件
. 在项目中,所有模块的配置参数都在顶层的 build.gradle 文件中配置。
如果在 build.gradle 中定义了一些属性,在 manifest 文件中不必再定义,如果构建文件中不包含某个属性,manifest 中该属性就会被用作后备。
. 任务 task
(1). assemble: 为每个构建版本构建一个 APK, 任务默认依赖于 assembleDebug 和 assembleRelease,如果执行命令./gradlew assemble 会生成 release 和 debug 两个 apk.
(2). clean: 删除所有的构建内容;
(3). check: 运行 Lint 检查,如果 Lint 发现一个问题,则可终止构建;
(4). build: 同时运行 assemble 和 check
./gradlew check 会生成一份 Lint 报告,在 app/build/outputs 目录下,名称为 lint-results.html, 该报告包含所有的警告和错误,以及一份详细的说明和一个相关文档的连接。
自定义构建
. BuidConfig 的设置
可以在构建类型 buildTypes 中设置 releas 和 debug 版本同的信息, 例如配置不同的 url
// 构建类型
buildTypes {
release {
minifyEnabled false // 是否开启混淆
shrinkResources false // 自动缩减资源,需要同时与 minifyEnabled 开启
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 混淆配置文件
// 配置log,在 Release 版本中不打印,
buildConfigField "boolean", "LOG_CALLS", "false";
// 配置不同的 URL
buildConfigField "String", "API_URL", "\"Http://example.com/api\""
}
debug {
buildConfigField "boolean", "LOG_CALLS", "true";
buildConfigField "String", "API_URL", "\"Http://texst.example.com/api\""
}
}
在 java 代码中 BuildConfig.API_URL 引用即可;
. 项目范围的设置
可以在顶层的 build.gradle 中添加一个自定义属性的 ext 代码块
// 自定义属性
ext {
compileSdkVersion = 25
buildToolsVersion = "25.0.3"
}
然后在模块的的 build.gradle 中使用 rootProject 来获取属性
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
}
三. 基本自定义构建
1. 依赖仓库
Gradle 支持三种不同的依赖仓库: Maven, Ivy 和静态文件或文件夹.
在顶项目根目录下的 build.gradle
allprojects {
repositories {
// jcenter 仓库
jcenter()
// Maven Central
mavenCentral()
// 本地 Maven 仓库
mavenLocal()
// 自有的 Maven 插件, 例子
maven {
url "http://repo.acmecorp.com/maven2"
}
// 团队自己的仓库
maven {
url "http://repo.acmecorp.com/maven2"
credentials {
username '****'
password '*****'
}
}
}
}
四. 依赖管理
1. 本地依赖和项目依赖
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) // 本地依赖
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
// 依赖项目
compile project(':mylibrary')
compile 'com.android.support:appcompat-v7:25.3.1'
// 测试
testCompile 'junit:junit:4.12'
// 可以针对特定的 flavor 添加 Junit
testXiaomiCompile 'junit:junit:4.12'
}
上面我们看到有 compile, 和 testCompile 其实 gradle 可以进行不同的配置
. compile 是默认配置,在编译主应用时包含所有的依赖。
. testComplie 测试依赖
. 针对特定的 variant 的依赖配置,这里的例子是 Xiaomi
.apk, 该依赖只会 被打包到 APK, 而不会添加到编译路径
.provided 与 apk 刚好相反,其依赖不会被打包进 APK.
五. 创建构建 Variant
1. 构建类型
构建类型除了 Release 和 debug 外,可以自定义类型
// 构建类型
buildTypes {
release {
minifyEnabled false // 是否开启混淆
shrinkResources false // 自动缩减资源,需要同时与 minifyEnabled 开启
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 混淆配置文件
// 配置log,在 Release 版本中不打印,
buildConfigField "boolean", "LOG_CALLS", "false";
// 配置不同的 URL
buildConfigField "String", "API_URL", "\"Http://example.com/api\""
// 添加签名信息
// signingConfig signingConfigs.releas
// 指定渠道产品特定签名
// productFlavors.xiaomi.signingConfig signingConfigs.xiaomi
}
debug {
buildConfigField "boolean", "LOG_CALLS", "true";
buildConfigField "String", "API_URL", "\"Http://texst.example.com/api\""
// signingConfig signingConfigs.debug
// 开启测试覆盖率
// testCoverageEnabled = true
}
// 自定义构建类型(命令行可以 ./gradlew assembleStaging)
staging {
staging.initWith(buildTypes.debug) // 复制一个已经存在的构建类型所有属性,可以重写,例如下面的 API_URL
applicationIdSuffix ".staging" // 生成的 applicationId 变成 包名.staging, 这里是 cash.juzhongke.com.gradledetaildemo.staging
versionNameSuffix "staging"
buildConfigField "String", "API_URL", "\"Http://staging.example.com/api\""
// signingConfig signingConfigs.staging
}
}
2. 源集
当创建一个新的构建类型时,Gradle 也会创建一个新的源集。源集目录名称默认和构建类型相同。该目录不是在定义新的构建类型时自动创建的,需要在构建类型使用自定义的源码和资源之前,手动创建该源集目录。
上图除了标准的 debug 和 Release ,还有一个额外 staging 构建类型的目录结构。
使用不同源集目录,可以构建类型自己的属性,例如,我们可以定义不同的包名,
详情可参考美团技术团队的《美团Android自动化之旅—适配渠道包》
3.product flavor
可以构建不同版本,用于多渠道打包
// 不同渠道版本
productFlavors {
commonsoon {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "commonsoon"]
// 可以自定义自己的 applicationId
applicationId 'cash.juzhongke.com.gradledetaildemo.commonsoon'
versionCode 3
minSdkVersion 23
}
zhushou91 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "zhushou91"]
}
market360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "market360"]
}
xiaomi {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
}
wandoujia {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
}
4.构建 Variant
构建 variant 是构建类型和product flavor 结合的结果。点击 Android Studio 左下角的 Build Variant 可以看到
5. variant 过滤器
通过 variants 过滤器忽略一些 variant
android {
// variant 过滤器,这里是忽略 xiaomi release 版本, 在 BuildVariants 中可以看到结果
android.variantFilter { variant ->
if (variant.buildType.name.equals('release')){
variant.getFlavors().each(){ flavor ->
if (flavor.name.equals('xiaomi')){
variant.setIgnore(true);
}
}
}
}
}
上面的例子是过滤掉 xiaomirelease 版本,在 Build Variant 中,我们就看不到了
这里的过滤在 Jenkins 集成的时候特别有用。
6. 签名配置
如果有一个付费版和免费版或针对不同用户的不同应用,可以为每个 flavor
signingConfigs {
releas {
storeFile file(KEY_STORE_FIELD)
keyAlias
keyPassword
storePassword
}
debug {
storeFile file()
keyAlias
keyPassword
storePassword
}
staging.initWith(signingConfigs.releas) // staging 和 release 版本一样的签名信息
// 可以为特定的 flavor 签名
xiaomi {
storeFile file()
keyAlias
keyPassword
storePassword
}
}
六. 创建任务和插件
加速多模块构建
在根目录下的 gradle.properities
# 并行构建项目, 可以加快构建项目
org.gradle.parallel=true
开启了虽然可以加快构建速度,有时候可能会失败。
使用命令行可以看到开启的信息
$ ./gradlew assemble
Parallel execution is an incubating feature.
七. 高级自定义构建
1. 使用任务来简化 release 过程
如果是配置签名
signingConfigs {
releas {
storeFile file("release.keystore")
keyAlias "Releasekey"
keyPassword "password"
storePassword "password"
}
这样密码已明文方式存放,不安全。可以通过以 task 来构建
在项目的根目录下创建一个 private.properties 文件,然后添加属性;
然后在module 目录下的 builde.gradle 添加 task
// 定义一个任务来获取 Release Password
task getReleasePassword << {
def keypassword = ''
def storepassword = ''
def keyalies = ''
if (rootProject.file('private.properties').exists()){
Properties properties = new Properties();
properties.load(rootProject.file('private.properties')
.newDataInputStream())
keypassword = properties.getProperty('release.password')
storepassword = properties.getProperty('release.storepassword')
keyalies = properties.getProperty('release.keyalies')
}
// 如果password 为空,private.properties 文件找不到,则询问控制台用户输入
if (!keypassword?.trim()){
keypassword = new String(System.console().readPassword("\nWhat's the secret password?"))
}
android.signingConfigs.release.keyPassword = keypassword
android.signingConfigs.release.storePassword = storepassword
android.signingConfigs.release.keyAlias = keyalies
}
// 运行时才添加,相当于 Hook
tasks.whenTaskAdded { theTask ->
if (theTask.name.contains("Release")){
theTask.dependsOn "getReleasePassword"
}
}
修改后的签名设置
signingConfigs {
release {
storeFile file(KEY_STORE_FIELD)
}
其中 KEY_STORE_FIELD 是 keystore 的路径,在 gradle.properties 上面设置
KEY_STORE_FIELD = E:\\work\\testkeystore\\gradleDemo.jks
2. 自动命名 apk
在 module 的 build.gradle 中
// 自动命名 apk
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def file = output.outputFile
output.outputFile = new File(file.parent,
file.name.replace(".apk", "-${variant.versionName}.apk"))
}
}
这里在 jenkins 持续集成时会用到。
3. 缩减资源
自动缩减
buildTypes {
release {
minifyEnabled false // 是否开启混淆
shrinkResources false // 自动缩减资源,需要同时与 minifyEnabled 开启
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro' // 混淆配置文件
}
}
手动缩减
defaultConfig {
applicationId "cash.juzhongke.com.gradledetaildemo"
minSdkVersion 22
targetSdkVersion 25
versionCode 1
versionName "1.0"
// 收到缩减 resConfigs 配置保留资源
resConfigs "en", "cn", "da" // 例如保留英语,中文,丹麦的字符串
resConfigs "hdpi", "xhdpi", "xxhdpi"
}
注:以上内容摘自《Gradle for Android 中文版》 一书