此页面以配置构建概览[Configure your build overview]为基础,向您介绍如何配置构建变体,以便从同一个项目中创建应用的不同版本,以及如何正确地管理依赖项并签署配置[ properly manage your dependencies and signing configurations]。
每个构建变体都代表您可以为应用构建的一个不同版本。例如,您可能希望构建应用的免费版本(只提供有限的内容)和付费版本(提供更多内容)。您还可以针对不同的设备、根据 API 级别或其他设备变体[device variations]构建应用的不同版本。然而,如果您希望根据设备 ABI 或屏幕密度构建不同的版本,则请改用APK 拆分。
构建变体是 Gradle 按照特定规则集[specific set of rules]合并[combine]在构建类型和产品风味中配置的设置、代码和资源所生成的结果。您并不直接配置构建变体,而是配置组成变体的构建类型和产品风味。
例如,一个“演示”产品风味可以指定不同的功能和设备要求,例如自定义源代码[custom source code]、资源和最低 API 级别,而“调试”构建类型则应用不同的构建和打包设置,例如调试选项和签署密钥[debug options and signing keys]。最终生成的构建变体是应用的“演示调试”版本,其既包含“演示”产品风味中包含的各种配置和资源,又包含“调试”构建类型和main/源集[source set]。
配置构建类型
您可以在模块级[module-level]build.gradle文件的android {}代码块内部创建和配置构建类型。当您创建新模块时,Android Studio 会自动为您创建调试和发布这两种构建类型。尽管调试构建类型不会出现在构建配置文件中,Android Studio 会为其配置debuggable true。这样,您可以在安全的 Android 设备上调试应用并使用通用调试密钥库[a generic debug keystore]配置 APK 签署。
android {
defaultConfig {
manifestPlaceholders = [hostName:"www.example.com"]
...
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
}
debug {
applicationIdSuffix ".debug"
debuggable true
}
/** The `initWith` property allows you to copy configurations from other build types, then configure only the settings you want to change. This one copies the debug build type, and then changes the manifest placeholder and application ID. */
staging {
initWith debug
manifestPlaceholders = [hostName:"internal.example.com"]
applicationIdSuffix ".debugStaging"
}
}
}
/** The `initWith` property allows you to copy configurations from other build types, then configure only the settings you want to change. This one copies the debug build type, and then changes the manifest placeholder and application ID. */
注:当您对构建配置文件进行更改时,Android Studio 会要求您为项目同步新配置。要同步项目,您可以点击在做出更改后立即出现在通知栏中的Sync Now,也可以点击工具栏中的Sync Project。如果 Android Studio 通知配置出现错误,会显示Messages窗口,具体描述该问题。
All flavors must belong to a named flavor dimension, which is a group of product flavors. You must assign分配、指定 flavors to a flavor dimension, even if you intend to you use only a single dimension; otherwise you will get the following build error:
Error:All flavors must now belong to a named flavor dimension.
The flavor ‘flavor_name‘ is not assigned to a flavor dimension.
Tip: The plugin tries to match variants of your app with those of local library dependencies[插件会尝试将应用的变体与本地库依赖项的变体进行匹配]. Because variant-aware dependency matching relies on[因为变体感知依赖关系匹配依赖于...] how you name flavor dimension, name your flavor dimensions carefully. Doing so gives you more control over[这样做可以让您更好地控制] which code and resources from your local dependencies are matched with each version of the app.
The following code sample creates a flavor dimension named "version" and adds "demo" and "full" product flavors. These flavors provide their own applicationIdSuffix and versionNameSuffix:
android {
...
defaultConfig {...}
buildTypes {
debug{...}
release{...}
}
flavorDimensions "version" // Specifies one flavor dimension.
productFlavors {
demo {
// Assigns this product flavor to the "version" flavor dimension.
dimension "version"// This property is optional if you are using only one dimension.
applicationIdSuffix ".demo"
versionNameSuffix "-demo"
}
full {
dimension "version"
applicationIdSuffix ".full"
versionNameSuffix "-full"
}
}
}
22
22
1
android {
2
...
3
defaultConfig {...}
4
buildTypes {
5
debug{...}
6
release{...}
7
}
8
flavorDimensions"version"// Specifies one flavor dimension.
9
productFlavors {
10
demo {
11
// Assigns this product flavor to the "version" flavor dimension.
12
dimension"version"// This property is optional if you are using only one dimension.
13
applicationIdSuffix".demo"
14
versionNameSuffix"-demo"
15
}
16
full {
17
dimension"version"
18
applicationIdSuffix".full"
19
versionNameSuffix"-full"
20
}
21
}
22
}
注:要利用 Google Play 中的 Multiple APK Support 分发您的应用,请为所有变体分配相同的 applicationId 值并为每个变体分配一个不同的 versionCode。要在 Google Play 中以独立应用的形式分发应用的不同变体,您需要为每个变体分配一个不同的 applicationId。
下面的代码示例使用flavorDimensions属性创建一个“mode”风味维度以"full" and "demo"产品风味,以及一个“api”风味维度以基于 API 级别组织产品风味配置:
android {
buildTypes {
debug {...}
release {...}
}
/** Specifies指定 the flavor dimensions you want to use. The order in which you list each dimension determines决定了 its priority优先级, from highest to lowest, when Gradle merges合并 variant sources and configurations. You must assign分配给 each product flavor you configure to one of the flavor dimensions. */
flavorDimensions "api", "mode"
productFlavors {
demo {
dimension "mode" // Assigns this product flavor to the "mode" flavor dimension.
}
full {
dimension "mode"
}
/** Configurations in the "api" product flavors override覆盖 those in "mode" flavors and the defaultConfig {} block. Gradle determines确定 the priority between flavor dimensions based on根据 the order in which they appear next to the flavorDimensions property above--the first dimension has a higher priority than the second, and so on. */
minApi24 {
dimension "api"
minSdkVersion ‘24‘
/** To ensure the target device receives the version of the app with the highest compatible API level[要确保目标设备接收具有最高兼容API级别的应用程序版本], assign分配 version codes in increasing value with API level. */
versionCode 30000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi24"
}
minApi23 {
dimension "api"
minSdkVersion ‘23‘
versionCode 20000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi23"
}
minApi21 {
dimension "api"
minSdkVersion ‘21‘
versionCode 10000 + android.defaultConfig.versionCode
versionNameSuffix "-minApi21"
}
}
}
...
43
43
1
android {
2
buildTypes {
3
debug {...}
4
release {...}
5
}
6
7
/** Specifies指定 the flavor dimensions you want to use. The order in which you list each dimension determines决定了 its priority优先级, from highest to lowest, when Gradle merges合并 variant sources and configurations. You must assign分配给 each product flavor you configure to one of the flavor dimensions. */
8
flavorDimensions"api", "mode"
9
10
productFlavors {
11
demo {
12
dimension"mode"// Assigns this product flavor to the "mode" flavor dimension.
13
}
14
15
full {
16
dimension"mode"
17
}
18
19
/** Configurations in the "api" product flavors override覆盖 those in "mode" flavors and the defaultConfig {} block. Gradle determines确定 the priority between flavor dimensions based on根据 the order in which they appear next to the flavorDimensions property above--the first dimension has a higher priority than the second, and so on. */
20
minApi24 {
21
dimension"api"
22
minSdkVersion‘24‘
23
/** To ensure the target device receives the version of the app with the highest compatible API level[要确保目标设备接收具有最高兼容API级别的应用程序版本], assign分配 version codes in increasing value with API level. */
默认情况下,Android Studio 会创建main/源集和目录,用于存储您要在所有构建变体之间共享的一切资源。然而,您可以创建新的源集来控制 Gradle 要为特定的构建类型、产品风味(以及使用风味维度时的产品风味组合)和构建变体编译和打包的确切文件。例如,您可以在main/源集中定义基本的功能,使用产品风味源集针对不同的客户更改应用的品牌,或者仅针对使用调试构建类型的构建变体包含特殊的权限和日志记录功能。
android {
sourceSets {
main { // Encapsulates将包封 configurations for the main source set.
java.srcDirs = [‘other/java‘] // Changes the directory for Java sources. default is ‘src/main/java‘.
/** If you list multiple directories, Gradle uses all of them to collect sources. Because Gradle gives these directories equal priority, if you define the same resource in more than one directory, you get an error when merging resources. */
res.srcDirs = [‘other/res1‘, ‘other/res2‘] //default is ‘src/main/res‘
/** Note: You should avoid specifying a directory which is a 【parent】 to one or more other directories you specify. For example, avoid the following: res.srcDirs = [‘other/res1‘, ‘other/res1/layouts‘, ‘other/res1/strings‘]. You should specify either only the root ‘other/res1‘ directory, or only the nested ‘other/res1/layouts‘ and ‘other/res1/strings‘ directories. */
/** For each source set, you can specify only one Android manifest. By default, Android Studio creates a manifest for your main source set in the src/main/ directory. */
manifest.srcFile ‘other/AndroidManifest.xml‘
}
androidTest { // Create additional blocks to configure other source sets.
/** If all the files for a source set are located under a single root directory, you can specify that directory using the setRoot property. When gathering搜集 sources for the source set, Gradle looks only in locations relative to the root directory you specify. For example, after applying the configuration below for the androidTest source set, Gradle looks for Java sources only in the src/tests/java/ directory. */
setRoot ‘src/tests‘
}
}
}
1
android {
2
sourceSets {
3
main { // Encapsulates将包封 configurations for the main source set.
4
java.srcDirs= [‘other/java‘] // Changes the directory for Java sources. default is ‘src/main/java‘.
5
6
/** If you list multiple directories, Gradle uses all of them to collect sources. Because Gradle gives these directories equal priority, if you define the same resource in more than one directory, you get an error when merging resources. */
7
res.srcDirs= [‘other/res1‘, ‘other/res2‘] //default is ‘src/main/res‘
8
9
/** Note: You should avoid specifying a directory which is a 【parent】 to one or more other directories you specify. For example, avoid the following: res.srcDirs = [‘other/res1‘, ‘other/res1/layouts‘, ‘other/res1/strings‘]. You should specify either only the root ‘other/res1‘ directory, or only the nested ‘other/res1/layouts‘ and ‘other/res1/strings‘ directories. */
10
11
/** For each source set, you can specify only one Android manifest. By default, Android Studio creates a manifest for your main source set in the src/main/ directory. */
12
manifest.srcFile‘other/AndroidManifest.xml‘
13
}
14
15
androidTest { // Create additional blocks to configure other source sets.
16
17
/** If all the files for a source set are located under a single root directory, you can specify that directory using the setRoot property. When gathering搜集 sources for the source set, Gradle looks only in locations relative to the root directory you specify. For example, after applying the configuration below for the androidTest source set, Gradle looks for Java sources only in the src/tests/java/ directory. */
注:如果您 combine multiple product flavors,产品风味之间的优先级将由它们所属的风味维度决定。When listing flavor dimensions with the android.flavorDimensions property, product flavors that belong to the first flavor dimension you list have a higher priority than those belonging to the second flavor dimension,以此类推。此外,与属于各个产品风味的源集相比,您为产品风味组合创建的源集拥有更高的优先级。
You can configure a dependency for a specific build variant or testing source set by prefixing前缀 the name of the build variant or testing source set before the Implementation keyword, as shown in the following example.
dependencies {
freeImplementation project(":mylibrary") // Adds the local "mylibrary" module as a dependency to the "free" flavor.
testImplementation ‘junit:junit:4.12‘ // Adds a remote binary dependency only for local tests.
androidTestImplementation ‘com.android.support.test.espresso:espresso-core:3.0.2‘ // Adds a remote binary dependency only for the instrumented test APK.
}
1
dependencies {
2
freeImplementationproject(":mylibrary") // Adds the local "mylibrary" module as a dependency to the "free" flavor.
3
testImplementation‘junit:junit:4.12‘// Adds a remote binary dependency only for local tests.
4
androidTestImplementation‘com.android.support.test.espresso:espresso-core:3.0.2‘// Adds a remote binary dependency only for the instrumented test APK.