不知道是什么网络问题,上午一直发不了博客,其它页面基本正常,就是在写博客这里,每次打开都是响应超时。刚才用了VPN,顺便试了一下,竟然能够编辑。想是CDN之类的问题吧。
这次翻译的是Gradle 插件用户指南,也就是Gradle上的Android插件的官方文档。文档非常长,加上近期激情不够,翻译得有些慢。到昨天为止,才译到第四章。今天先发前三章。
本文译自Android官方技术文档《Gradle Plugin User Guide》,原文地址:http://tools.android.com/tech-docs/new-build-system/user-guide。
翻译不易,转载请注明CSDN博客上的出处:
http://blog.csdn.net/maosidiaoxian/article/details/41944325
翻译工作耗时费神,假设你认为本文翻译得还OK,请点一下“顶”,我在精神上会倍受鼓舞的,谢谢。翻译如有错讹,敬请指正。
Gradle 插件用户指南
简单介绍
新构建系统的目标
- 能够非常easy地重用代码和资源
- 能够非常easy地创建应用程序的几个变种,不管是多APK分发还是不同定制版的应用程序
- 能够非常easy地配置、 扩展和自己定义构建过程
- 好的 IDE 集成
为什么是 Gradle ?
基于Gradle的下面特点,我们选择了它:
- 域特定语言 (DSL) 来描写叙述和处理构建逻辑
- 构建文件基于 Groovy ,并同意通过 DSL来混合声明性元素,以及使用代码来处理 DSL 元素以提供自己定义逻辑。
- 基于 Maven 和 Ivy 的内置依赖管理。
- 很灵活。同意使用最佳实现,但并不强制自己的实现方式。
- 插件能够提供自己的 DSL 和API供构建文件使用。
- 良好的Tooling API 供 IDE 集成
要求
- Gradle 版本号须要 1.10,1.11或 1.12。插件版本号须要 0.11.1
- SDK Build Tools版本号要求为 19.0.0。某些功能可能须要更高版本号。
基本项目
简单的构建文件
apply plugin: 'java'
这里配置使用了Gradle内置的 Java 插件。该插件提供用于构建并測试 Java 应用程序所须要的东西。
最简单的 Android 项目的 build.gradle 则是下面内容:
buildscript {repositories {mavenCentral()
}dependencies {classpath 'com.android.tools.build:gradle:0.11.1'}}apply plugin: 'android'android {compileSdkVersion 19
buildToolsVersion "19.0.0"
}
buildscript { ... }配置了驱动构建的代码。
在上面的这样的情况中,它声明了使用 Maven *库,而且对一个Maven 文件有一个类路径依赖。这个文件是包括 Gradle Android 插件的 0.11.1版本号的库
注: 这仅仅会影响执行构建的代码,不会影响项目的源码。项目本身须要定义它自己的仓库和依赖关系。稍后会提及这部分。
然后,和先前的提到的 Java 插件一样,这里配置使用了 android插件。
最后, android { ... }配置了用于 android 构建的全部參数。这是Android DSL的入口。
默认情况下,仅仅须要配置编译目标,以及build-tools的版本号。它通过compileSdkVersion和buildtoolsVersion属性来完毕。
重要提示:你应该仅仅配置使用这个android插件。假设同一时候配置使用了java插件也会导致构建错误。
注:您还须要一个local.properties文件,通过sdk.dir属性来设置 SDK 的位置,而且所设置的这个SDK要求存在。
或者,您也能够设置一个ANDROID_HOME环境变量。这两种方法之间没什么区别,你喜欢,你选择。
项目结构
基本项目開始于两个名为“source sets”的组件。即主源码和測试代码。它们分别在:
- src/main/
- src/androidTest/
对于 Java 和 Android 插件,Java 源码和 Java 资源的位置例如以下:
- java/
- resources/
- AndroidManifest.xml
- res/
- assets/
- aidl/
- rs/
- jni/
注: src/androidTest/AndroidManifest.xml是不须要的,由于它会被自己主动创建。
配置项目结构
sourceSets {main {java
{srcDir
'src/java'
}
resources
{
srcDir
'src/resources'
}
}
}
注: srcDir实际上会将给定的目录加入到现有的源目录列表中 (这在Gradle 文档中没有提及,但这是实际的行为)。
假设要替换默认的源目录,您就要使用传入一个路径数组的srcDirs来取代。下面是使用涉及的对象的还有一种不同的方法:
sourceSets {main.java.srcDirs = ['src/java']main.resources.srcDirs = ['src/resources']}
欲了解很多其它信息,请參阅 Gradle 文档中关于 Java 插件的内容,见这里。
Android 插件使用类似的语法,但由于它使用它自己的sourceSets,所以在android对象里面来实现。
这里有一个样例,使用旧的项目结构的主源代码并又一次映射androidTest sourceSet 到tests目录:
android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs
= ['src']
resources.srcDirs
= ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs
= ['src']
res.srcDirs
= ['res']
assets.srcDirs = ['assets']
}
androidTest.setRoot('tests')
}
}
注意: setRoot()会将整个sourceSet (和它的子目录) 移到一个新的目录中。这将移动src/androidTest/*到tests/*
下。这是 Android 专用的,不适用于 Java sourceSets。
这也是一个“迁移”的样例。
构建任务
常规任务
-
assemble
组装项目的输出的任务 -
check
执行全部检查的任务。 -
build
这个任务将运行assemble和check。 -
clean
这个任务将清理项目的输出
assemble,check和build这些任务,实际上不做不论什么事情。他们是锚记任务,用于让插件加入实际的任务去做这些事情。这同意您可以调用相同的任务,不管项目的类型是什么,或者是配置使用了什么插件
。
比如,配置使用findbugs插件将创建一个新的任务和使check任务依赖于它,使得每当调用check任务时都会调用到它。
您能够从命令行中执行以下的命令来获取更高级别的任务:
gradle tasks
gradle tasks --all
在没有变化的情况下,执行两次build会使 Gradle 报告全部任务为UP-TO-DATE状态,这个状态意味着没有不论什么事情须要执行。这同意任务正确地相互依赖而无需不必要的构建操作。
Java 项目任务
- assemble
-
jar
这个任务将创建输出。
-
jar
- check
-
test
这个任务将执行測试。
-
test
jar任务本身会直接或间接地依赖其它任务: 比如,classes任务用于编译 Java 代码。
testClasses任务用于编译測试,但它非常少会被调用,由于test任务依赖于它
(以及classes任务)。
普通情况下,你将可能永远仅仅调用assemble或check,而无视其它任务。
在这里,你能够看到Java 插件的全部任务和对它们的描写叙述。
Android 任务
- assemble
组装项目的输出的任务 - check
执行全部检查的任务。 -
connectedCheck
执行须要一个已连接的设备或模拟器的检查。它们将在全部已连接的设备上并行执行。 - deviceCheck
使用 API 连接到远程设备执行检查。这一个是在 CI server上使用的。 - build
这项任务将运行assemble 和 check - clean
这个任务将清理项目的输出
注意到,build任务不依赖于deviceCheck或connectedCheck。
Android 项目具有至少两个输出: debug版本号的APK 和release版本号的 APK。这里的每个输出都有自己的锚记任务,以便单独构建它们:
- assemble
- assembleDebug
- assembleRelease
提示:在命令行上,Gradle 支持任务名称的驼峰命名法的简写。比如:
gradle aR
gradle assembleRelease
check锚记任务有它们自己的依赖项:
- check
- lint
- connectedCheck
- connectedAndroidTest
- connectedUiAutomatorTest (暂未实现)
- deviceCheck
- 这个任务依赖于当其它插件实现了測试扩展点时创建的任务。
最后,该插件为全部构建类型 (debug、release、test)创建了omstal/uninstall
任务,仅仅要他们能够被安装(须要签名)。
主要的构建定制
清单条目
- minSdkVersion
- targetSdkVersion
- versionCode
- versionName
- applicationId (有效的包名 —— 很多其它的信息请參阅ApplicationId
与packageName) - 用于測试应用程序的包名
- Instrumentation test runner
演示样例:
android {compileSdkVersion 19
buildToolsVersion "19.0.0"
defaultConfig {versionCode
12
versionName
"2.0"
minSdkVersion
16
targetSdkVersion
16
}}
在android元素的内部的defaultConfig元素是定义全部这些配置的地方。
在构建文件里描写叙述它的强大之处是它能够是动态的。
比如,能够从文件里的某处或使用一些自己定义的逻辑读取版本号信息:
def computeVersionName() {...}android {compileSdkVersion 19buildToolsVersion "19.0.0"defaultConfig {versionCode 12versionName computeVersionName()
minSdkVersion 16
targetSdkVersion 16
}}
假设一个属性未通过 DSL 来设置,它将使用默认值。下表描写叙述了对于未设置的属性的处理方式。
属性名称 | DSL 对象中的默认值 | 默认值 |
versionCode | -1 | 假设在清单中存在,则使用清单中的值 |
versionName | null | 假设在清单中存在,则使用清单中的值 |
minSdkVersion | -1 | 假设在清单中存在,则使用清单中的值 |
targetSdkVersion | -1 | 假设在清单中存在,则使用清单中的值 |
applicationId | null | 假设在清单中存在,则使用清单中的值 |
testApplicationId | null | applicationId + “.test” |
testInstrumentationRunner | null | android.test.InstrumentationTestRunner |
signingConfig | null | null |
proguardFile | N/A (仅仅设置) | N/A (仅仅设置) |
proguardFiles | N/A (仅仅设置) | N/A (仅仅设置) |
第二列的值是非常重要的,假设您在构建脚本中使用自己定义逻辑查询这些属性的话。比如,您能够编写:
if (android.defaultConfig.testInstrumentationRunner == null) {// assign a better default...}
这是为了防止解析应用程序的清单,除非真的非常须要。
构建类型
调试版本号使用自己主动创建的密钥/证书签名,而且密钥/证书的username/password是已知的(以防止构建过程中须要相关的信息)的。release版本号在构建的时候不会进行签名,须要在之后进行签名。
这个配置是通过一个叫BuildType的对象来完毕的。默认情况下,2 个实例会被创建,各自是debug版和release版。
Android 插件同意自己定义这两个实例,以及创建其它的构建类型。它通过buildTypes DSL 容器来实现:
android {buildTypes {debug
{
applicationIdSuffix ".debug"
}jnidebug.initWith(buildTypes.debug)jnidebug {packageNameSuffix ".jnidebug"jniDebuggable true}}}
上面的代码段可实现下面操作:
- 配置默认的Debug Build Type:
- 设置包名为<app appliationId>.debug,以便可以在同样的设备上安装debug和release两个版本号的apk
- 创建一个叫jnidebug的新的BuildType对象 ,并将其配置为debug生成类型的一个副本。
- 通过启用 JNI 组件的debug构建,并加入不同的包后缀,继续配置jnidebug。
创建新的 Build Types 就是简单地在buildTypes下加入一个新的元素,然后调用 initWith()或者是使用一个闭包来配置。
下面是可能用到的属性和它们的默认值:
属性名称 | 用于 debug的默认值 | 用于 release/其它 的默认值 |
debuggable | true | false |
jniDebuggable | false | false |
renderscriptDebuggable | false | false |
renderscriptOptimLevel | 3 | 3 |
applicationIdSuffix | null | null |
versionNameSuffix | null | null |
signingConfig | android.signingConfigs.debug | null |
zipAlignEnabled | false | true |
minifyEnabled | false | false |
proguardFile | N/A (仅仅设置) | N/A (仅仅设置) |
proguardFiles | N/A (仅仅设置) | N/A (仅仅设置) |
除了这些属性,Build Types还会影响到构建的代码和资源。
对每一个Build Type都会创建一个自己主动匹配的sourceSet,默认位置为
src/<buildtypename>/
与不论什么其它source set一样,生成类型的source set的位置也是能够又一次设置的:
android {sourceSets.jnidebug.setRoot('foo/jnidebug')}
已经提到过的assembleDebug和assembleRelease这两个任务,这里也会讲一下它们是怎么来的。当debug和releaseBuild
Types被预创建的时候,他们的任务也会被自己主动创建。然后,
上面的build.gradle片段也会生成一个assembleJnidebug任务,而且assemble将会依赖于它,就像它依赖于assembleDebug和assembleRelease任务一样。
提示: 请记住您能够输入gradle aJ来执行assembleJnidebug任务。
可能会用到的情况:
- release模式下不须要,但debug模式下须要的权限
- 自己定义的debug实现
- 为调试模式使用不同的资源 (比如某个资源的值与签名证书相绑定时)。
BuildType的代码和资源通过下面方式被使用:
- manifest将被合并到应用程序的manifest中
- 代码仅仅是作为还有一个源目录来起作用
- 资源将覆盖main里面的资源,并替换已经存在的值。
签名配置
- 一个 keystore
- 一个 keystore 的password
- 一个 key 的别名
- 一个 key 的password
- 存储类型
签名文件的位置,key的名称,以及这两个password和存储类型,一起构成了一个签名配置 ( SigningConfig类型)
默认情况下,有一个debug的配置,配置使用了一个debug keystore。这个keystore使用了一个已知的key和一个已知的password。
这个debug keystore 位于$HOME/.android/debug.keystore,而且会在不存在时被创建。debug Build
Type被设置为自己主动使用此debug
SigningConfig。
你也能够创建其它配置,或者自己定义某个默认的内置配置。通过signingConfigs DSL 容器来实现:
android {signingConfigs {debug {storeFile file("debug.keystore")}myConfig {storeFile file("other.keystore")storePassword "android"keyAlias "androiddebugkey"keyPassword "android"}}buildTypes {foo {debuggable truejniDebuggable truesigningConfig signingConfigs.myConfig}}}
代码的代码还创建了一个新的Signing Config和使用新配置的新的Build Type 。
注:仅仅有位于默认位置下的debug keystores才会被自己主动创建。假设debug keystore的位置被更改了,它将不会在须要时自己主动创建。创建一个使用一个不同的名称SigningConfig,但使用了默认的debug keystore的路径,它也会被自己主动创建。换句话说,会不会被自己主动创建与keystore的路径有关,而与配置名称无关。
注: keystore的路径通常使用项目根文件夹的相对路径,但也能够是使用绝对路径,虽然这不推荐 (除了自己主动创建的debug keystore)。
执行ProGuard
android {
buildTypes {
release {
minifyEnabled true
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
flavor1 {
proguardFile 'some-other-rules.txt'
}
- proguard-android.txt
- proguard-android-optimize.txt