构建类型(Build Type)和产品渠道(Product Flavor)的结合,称之为构建变体(Build Variants)。
1.构建类型(Build Type)
构建类型用于定义如何去构建一个APP.每一种类型可以定义是否包含DEBUG信息,applicationId等信息。我们可以在buildTypes
代码块下定义构建类型,如下所示:
android {
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile
('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
我们可以很容易的创建自定义的构建类型,如下的构建类型定义了app id 后缀和版本名后缀以及API_URL:
android {
buildTypes {
//可以继承debug 构建类型
staging.initWith(buildTypes.debug)
staging {
applicationIdSuffix ".staging"
versionNameSuffix "-staging"
buildConfigField "String", "API_URL",
"\"http://staging.example.com/api\""
}
}
}
当我们新增一个构建类型时,Gradle 同时会创建新的source set,默认情况下,source set 的目录名和构建名称一致。但是这个目录不会主动被创建,如果需要用到,需要手动去创建它。下面是新增构建类型后的目录结构:
app
└── src
├── debug
│ ├── java
│ │ └── com.package
│ │ └── Constants.java
│ ├── res
│ │ └── layout
│ │ └── activity_main.xml
│ └── AndroidManifest.xml
├── main
│ ├── java
│ │ └── com.package
│ │ └── MainActivity.java
│ ├── res
│ │ ├── drawable
│ │ └── layout
│ │ └── activity_main.xml
│ └── AndroidManifest.xml
├── staging
│ ├── java
│ │ └── com.package
│ │ └── Constants.java
│ ├── res
│ │ └── layout
│ │ └── activity_main.xml
│ └── AndroidManifest.xml
└── release
├── java
│ └── com.package
│ └── Constants.java
└── AndroidManifest.xml
通过修改特定构建目录下的一些资源,可以实现不同的构建结果。但是,需要特别注意的是,java 文件资源是互斥的,就是说在main source set 中存在的java文件,不能在其他构建类型的对应位置存在,否则为提示重复定义;而Resource 文件则不同,在其他构建目录的单一资源文件(比如layout.xml)会覆盖main 目录的单一资源文件,非单一资源文件(比如string.xml,manifest.xml)则会合并在一起。如下示例:
main source set 下的 string.xml:
<resources>
<string name="app_name">TypesAndFlavors</string>
<string name="hello_world">Hello world!</string>
</resources>
和 staging source set 下的string.xml
<resources>
<string name="app_name">TypesAndFlavors STAGING</string>
<string name="title">Staing</string>
</resources>
合并后的结果如下:
<resources>
<string name="app_name">TypesAndFlavors STAGING</string>
<string name="hello_world">Hello world!</string>
<string name="title">Staing</string>
</resources>
每个构建类型可以有自己的依赖,Gradle 会为每个构建类型自动创建以来配置。比如想要为debug的构建类型单独添加依赖,可以这样做:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
//针对debug build type 类型的依赖
debugCompile 'de.mindpipe.android:android-logging-log4j:1.0.3'
}
2.产品渠道(Product Flavor)
构建类型用于定义同一APP的不同构建,产品渠道则用来定义统一APP的不同版本,比如付费版和免费版.通常,如果我们要对外发布不同版本的APP,则我们应该使用Product Flavor来实现,否则就可以使用Build Type.示例代码:
android {
productFlavors {
red {
applicationId 'com.gradleforandroid.red'
versionCode 3
}
blue {
applicationId 'com.gradleforandroid.blue'
minSdkVersion 14
versionCode 4
}
}
}
Product Flavor 有不同于Build Type的属性。它和defaultConfigure拥有同样的属性,所以在defaultConfigure中使用的属性都可以在Product Flavor中使用,比如verionCode,versionName等等。
同样的,Gradle 会为每个Product Flavor创建sourceSet目录。
产品渠道可以通过渠道标尺(flavor dimensions)来实现组合渠道,而不同重复定义某些属性。示例如下:
android {
flavorDimensions "color", "price"
productFlavors {
red {
flavorDimension "color"
}
blue {
flavorDimension "color"
}
free {
flavorDimension "price"
}
paid {
flavorDimension "price"
}
}
}
通过定义flavorDimensions,Gradle 会将不同dimensions的product flavoer组合成一个新的product flavor。特别注意的是,一旦定义额了flavorDimensions,就必须在product flavor中使用这些定义的值,否则会编译报错。以上的配置会产生如下的构建:
• blueFreeDebug and blueFreeRelease
• bluePaidDebug and bluePaidRelease
• redFreeDebug and redFreeRelease
• redPaidDebug and redPaidRelease
3.构建变体(Build Variants)
Build Variants 就是 Build Type 和product flavor 的组合结果。上面展示的8中构建结果就是8种构建变体。
Build Variants 同样可以有自己的source set 目录。比如blueFreeDebug
构建变体的source set 目录就是src/blueFreeDebug/java/
。
不同变体的资源和清单合并有固定的优先级,优先级如下所示:
Build Type >Flavor >Main > Dependencies
比如,如果某个资源同时在Flavor和Main 中定义,那么Flavor中的资源拥有更高的优先级,它会覆盖Main中的资源。
更多的资源合并规则可以看网址t http://tools.android.com/tech-docs/new-buildsystem/user-guide/manifest-merger.
构建变体的配置文件如下:
android {
buildTypes {
debug {
buildConfigField "String", "API_URL",
"\"http://test.example.com/api\""
}
staging.initWith(android.buildTypes.debug)
staging {
buildConfigField "String", "API_URL",
"\"http://staging.example.com/api\""
applicationIdSuffix ".staging"
}
}
productFlavors {
red {
applicationId "com.gradleforandroid.red"
resValue "color", "flavor_color", "#ff0000"
}
blue {
applicationId "com.gradleforandroid.blue"
resValue "color", "flavor_color", "#0000ff"
}
}
}
虽然定义了很多变体,但是在构建时我们可以过滤掉某些Build Variants。我们可以在顶级build.gradle文件中添加如下代码:
//过滤到blue flavor 和 release build type 组合的variants
android.variantFilter { variant ->
if(variant.buildType.name.equals('release')) {
variant.getFlavors().each() { flavor ->
if (flavor.name.equals('blue')) {
variant.setIgnore(true);
}
}
}
}
4.签名配置
在构建时我们通常要为各个变体配置签名信息。首先我们可以定义几种类型的签名配置:
android {
signingConfigs {
staging.initWith(signingConfigs.debug)
release {
storeFile file("release.keystore")
storePassword"secretpassword"
keyAlias "gradleforandroid"
keyPassword "secretpassword"
}
}
}
然后为各个变体指定签名配置。通常我们只需要在不同的Build Type 中指定 签名配置就可以了。如下所示:
android {
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
如果不同的Flavor 需要不同的签名信息,可以这么做:
android {
buildTypes {
release {
//为不同的flavor 指定不同的签名配置
productFlavors.red.signingConfig signingConfigs.red
productFlavors.blue.signingConfig signingConfigs.blue
}
}
}