gradle构建变种版本

为什么选择Gradle

如你是一个开发者,项目自动构建是你每天工作的一部分,难道你就不想让你的构建代码和你写的源代码一样可以扩展、测试和维护?Gradle的构建脚本是声明式的、可读的,可以清晰的表达意图。使用Groovy代替XML来写代码大大减少了构建代码的大小。更重要的是,Gradle集成了其他构建工具,比如Ant和Maven,使得原来的项目很容易迁徙到Gradle。

案例

  1. 不同的配置

    相信每位不容易的android开发者都会有这样的需求,某个项目一般会有一个测试服地址和一个正式服地址,项目版本迭代都是先在测试服上面测试通过后,服务器在部署正式服地址的服务器,然后在构建一个正式服地址给测试人员。测试服情况下app需要有一些日志开关或者一些只能在测试服出现的UI或者配置,没用gradle构建变种版本之前,我们一般都是手动去改那些配置

  2. 多渠道apk

    有这样的需求就是,应用能有收费版本或者免费版本或者会有不同的发包渠道,这种情况就是每个渠道版本的配置信息都是不一样的,如果渠道只有几个还好我们可以直接利用工具进行手动signature pak,一旦渠道有几十个的情况下。手动signature方式就不合适了,我们需要每个每个的去signature,这样就没法工作了。

配置多个变种版本

完整的变种版本配置

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
apply plugin: 'com.android.application'

def releaseTime() {
return new Date().format("MMddHHmm", TimeZone.getTimeZone("GMT+08:00"))
}

android {
flavorDimensions "default"
compileSdkVersion 26
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "com.jinwei.me"
minSdkVersion 18
targetSdkVersion 24
versionCode 1101
versionName "1.1.01"
multiDexEnabled = true

}

signingConfigs {
release {
storeFile file("./test")
storePassword "aaaaaa"
keyAlias "rc"
keyPassword "aaaaaa"
}
}

buildTypes {
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
signingConfig signingConfigs.release
applicationVariants.all { variant ->
variant.outputs.all { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = "Test${variant.productFlavors[0].name}.apk"
outputFileName = fileName
}
}
}
}
}

productFlavors {
正式服发版包 {
/*是否正式服地址*/
buildConfigField "boolean", "RELEASE", "true"
/*是否使用ANDROID_ID*/
buildConfigField "boolean", "ANDROID_ID", "true"
/*是否使用打开邮箱注册*/
buildConfigField "boolean", "OPEN_EMAIL", "false"
/*是否打开日志*/
buildConfigField "boolean", "OPEN_LOG", "false"
}
正式服 {
/*是否正式服地址*/
buildConfigField "boolean", "RELEASE", "true"
/*是否使用ANDROID_ID*/
buildConfigField "boolean", "ANDROID_ID", "false"
/*是否使用打开邮箱注册*/
buildConfigField "boolean", "OPEN_EMAIL", "true"
/*是否打开日志*/
buildConfigField "boolean", "OPEN_LOG", "true"
}
测试服 {
/*是否正式服地址*/
buildConfigField "boolean", "RELEASE", "false"
/*是否使用ANDROID_ID*/
buildConfigField "boolean", "ANDROID_ID", "false"
/*是否使用打开邮箱注册*/
buildConfigField "boolean", "OPEN_EMAIL", "true"
/*是否打开日志*/
buildConfigField "boolean", "OPEN_LOG", "true"
}

}
}
repositories {
mavenCentral()
google()
flatDir {
dirs 'libs'
}
}

dependencies {
testCompile 'junit:junit:4.12'

}

首先进入到app级别下的gradle中,gradle构建需要配置签名信息我们先配置一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
signingConfigs {
release {
storeFile file("./test")
storePassword "aaaaaa"
keyAlias "rc"
keyPassword "aaaaaa"
}
debug {
storeFile file("./test")
storePassword "aaaaaa"
keyAlias "rc"
keyPassword "aaaaaa"
}

这个信息可以ide生成一个key填写签名信息然后存储到app目录下面。

配置完后,接着在配置不同的版本。

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
30
31
32
33
productFlavors {
正式服发版包 {
/*是否正式服地址*/
buildConfigField "boolean", "RELEASE", "true"
/*是否使用ANDROID_ID*/
buildConfigField "boolean", "ANDROID_ID", "true"
/*是否使用打开邮箱注册*/
buildConfigField "boolean", "OPEN_EMAIL", "false"
/*是否打开日志*/
buildConfigField "boolean", "OPEN_LOG", "false"
}
正式服 {
/*是否正式服地址*/
buildConfigField "boolean", "RELEASE", "true"
/*是否使用ANDROID_ID*/
buildConfigField "boolean", "ANDROID_ID", "false"
/*是否使用打开邮箱注册*/
buildConfigField "boolean", "OPEN_EMAIL", "true"
/*是否打开日志*/
buildConfigField "boolean", "OPEN_LOG", "true"
}
测试服 {
/*是否正式服地址*/
buildConfigField "boolean", "RELEASE", "false"
/*是否使用ANDROID_ID*/
buildConfigField "boolean", "ANDROID_ID", "false"
/*是否使用打开邮箱注册*/
buildConfigField "boolean", "OPEN_EMAIL", "true"
/*是否打开日志*/
buildConfigField "boolean", "OPEN_LOG", "true"
}

}

buildConfigField就是我们需要用到的字段,可以看到每个产品的类型都是不一样的。

配置buildTypes,这里我们指定了signingConfig为release的签名 信息,就是我们刚刚配置的。如果有需求也可以指定debug的签名信息。这里的release{} debug{} build的时候会选择对应的build信息,applicationVariants.all 我们还自动对apk名字进行了命名。

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
30
buildTypes {
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
signingConfig signingConfigs.release
applicationVariants.all { variant ->
variant.outputs.all { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = "Test${variant.productFlavors[0].name}_${releaseTime()}.apk"
outputFileName = fileName
}
}
}
}
debug {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
signingConfig signingConfigs.release
applicationVariants.all { variant ->
variant.outputs.all { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = "Livu${variant.productFlavors[0].name}_${releaseTime()}.apk"
outputFileName = fileName
}
}
}
}
}

配置完成后进行编译,我们搜索一下类BuildConfig,可以看到build的时候已经自动读取了对应的配置信息了。然后我们可以根据这些字段信息来做对应的逻辑操作了,比如如果日志开关为true的情况下我们才打印log日志,如果RELEASE为true我们就使用正式服地址如果是false的话我们就使用测试服地址。

1
2
3
4
5
// Fields from product flavor: 测试服
public static final boolean ANDROID_ID = false;
public static final boolean OPEN_EMAIL = true;
public static final boolean OPEN_LOG = true;
public static final boolean RELEASE = false;

我们可以选择这里切换版本信息,对应的也会自动读取配置的信息。

手动打包的方式可以看也多了,三个不同类型的Flavors。

使用gradlew可以直接自动构建 mac下./gradlew开头 windows下面用gradlew开头

构建全部Flavors的debug和Release包

1
./gradlew build
1
2
3
gradlew assemble测试服Release build测试服的Release包
gradlew assemble测试服Deubg build测试服的Debug包
gradlew assembleRelease build全部Flavors的Release包

到这里就完成了变种版本的配置,基本来说比较简单。

后续的学习

Gradle In Action(Gradle实战)中文版

Gradle Android插件用户指南翻译