周末看完了「巧用Gradle构建Android应用」,故将新认知整理在此以便以后供自己以及有需要的人查看。
Gradle
Gradle构建过程实际上是执行DAG(Directed Acyclic Graph,有向无环图),允许定义自己的task并插入到其中。
build.gradle中Android块时Android DSL()的入口。依赖的语法
1
2
3
4
5
6
7//完整语法 (禁用传递依赖)
testCompile group: 'junit', name: 'junit', version: '4.12', transitive: false
//排除依赖
androidTestCompile('org.splckframeword:spock-core:1.0-groovy-2.4') {
exclude group: 'org.codehaus.groovy'
exclude group: 'junit'
}配置仓库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18repositories {
maven {
// 其中的username值和password值可以写在gradle.properties或者在执行gradlew命令时以参数输入
// ./gradlew -Puser=user_from_pFlag -Ppass=pass_from_pFlag
username 'username'
password 'password'
}
url 'http://repo.mycompany.com/maven2'
}
// 还可以在ext块中配置
ext {
if (!project.hasProperty('user')) {
def username = 'alice'
}
if (!project.hasProperty('pass')) {
def password = 'passpass'
}
}升级Gradle版本
1
2
3
4
5
6// 方法一
task wrapper(type: Wrapper) {
gradleVersion = 2.12
}
./gradlew wrapper
// 方法二:直接修改gradle-wrapper.properties文件的distributionUrl属性。签名
1
2
3
4
5
6
7
8
9
10
11
12android {
// ...other section...
signingConfigs {
release {
keyAlias 'my_alias'
keyPassword 'password'
storeFile file('/Users/kousen/keystores/myapp.ketstore')
storePassword 'password'
}
}
}
// 同样,密码可以放到gradle.properties中,或者以gradlew的参数输入构建类型
1
2
3
4
5
6
7buildTypes {
// 加后缀区分可同时安装在同一设备上
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-debug'
}
}产品定制&维度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15android {
productFlavors {
arrogant {
dimension 'attitude'
applicationId 'com.oreilly.helloword.arrg'
}
friendly {
dimension 'attitude'
applicationId 'com.oreilly.helloword.fund'
}
stark {
dimension 'client'
}
}
}自定义任务。Gradle的DSL API已经存在很多任务,如Copy、Wrapper和Exec等,这些任务可以简单地设置属性然后使用。比如Copy任务所包含的from和into属性。
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// 复制任务
task copyApks(type: Copy) {
from("$buildDir/outputs/apk") {
exclude '**/*unsigned.apk', '**/*unaligned.apk'
}
into '../apks'
}
// 显示所有可用任务的变种。这个任务中无论在doLast之前还是之后的所有事情都是在配置阶段执行,
// doLast块中的代码在运行阶段执行
// applicationVariants属性只针对com.android.application插件有效
// libraryVariants属性只针对com.android.library插件有效
task printVariantNames() {
doLast {
android.applicationVariants.all { variant ->
println variant.name
}
}
}
// 执行安装所有应用的变种的任务
// dependsOn属性显示这是配置阶段的一部分,而不是运行阶段。每一个变种名字都被首字母大写了
// 并且相应的安装任务也被添加到installDebugFlavors任务的一个依赖
task installDebugFlavors() {
android.applicationVariants.all { v ->
if (v.name.endWiths('Debug')) {
String name = v.name.capitalize()
dependsOn "install$name"
}
}
}延长ADB超时时长
1
2
3
4
5
6// 30秒
android {
adbOptions {
timeOutInMs = 30 * 1000
}
}添加自定义任务到构建过程
1
2
3
4
5
6
7
8
9// 基于assembleDebug的依赖意味着在运行copy任务之前所有调试APK都会被生成。
task copyApks (type: Copy, dependsOn: assembleDebug) {
from("$buildDir/outputs/apk") {
exclude '**/*unsigned.apk', '**/*unsigned.apk'
}
into '../apks'
}
// 如果想要在每次构建的时候都运行copyApks任务,将其作为build任务的一个依赖
build.dependsOn copyApks排除任务
1
2
3
4
5
6
7
8
9
10> ./gradlw build -x lint
// Gradle运行时,其组装了一个task graph,通过gradle获得这个图的引用,所有对这个图的操纵都需要发生
// 在其构建出来之后,所以需要使用whenReady属性
gradle.taskGraph.whenReady { graph ->
if (project.hasProperty('nolint')) {
graph.allTask.findAll {
it.name ==~/lint.*/}*.enabled = false
}
}
}性能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// gradle.properties
// 守护进程
org.gradle.daemon=true
// 按需配置设置
org.gradle.configureondemand=true
// 选择JVM设置 Xmx最大内存 Xms初始内存 XX:MaxPermSize永代久空间
// HeapDumpOnOutOfMemoryError发生时,将堆中情况导出到一个文件中
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError
// 使用dex选项
dexOptions {
incremental true
javaMaxHeapSize '2g'
jumboMode = true//运载dex文件中出现的大量字符串,可能需要配置ProdGuard
preDexLibraries = true
}