构建 build variants 构建变体

时间:2021-09-14 13:54:57

配置构建变体

Configure build variants

此页面以配置构建概览[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 签署。

如果您希望添加或更改特定设置,您可以将调试构建类型添加到您的配置中。以下示例为调试构建类型指定了 applicationIdSuffix,并配置了一个使用调试构建类型中的设置进行初始化的“staging”构建类型。

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"
        }
    }
}
24
24
 
1
android {
2
    defaultConfig {
3
        manifestPlaceholders = [hostName:"www.example.com"]
4
        ...
5
    }
6
    buildTypes {
7
        release {
8
            minifyEnabled true
9
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
10
        }
11
12
        debug {
13
            applicationIdSuffix ".debug"
14
            debuggable true
15
        }
16
17
/** 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. */
18
        staging {
19
            initWith debug
20
            manifestPlaceholders = [hostName:"internal.example.com"]
21
            applicationIdSuffix ".debugStaging"
22
        }
23
    }
24
}

:当您对构建配置文件进行更改时,Android Studio 会要求您为项目同步新配置。要同步项目,您可以点击在做出更改后立即出现在通知栏中的 Sync Now,也可以点击工具栏中的 Sync Project 构建 build variants 构建变体 。如果 Android Studio 通知配置出现错误,会显示 Messages 窗口,具体描述该问题。

如需详细了解对于构建类型可以配置的所有属性,请阅读构建类型 DSL 参考

配置产品风味

Configure product flavors

创建产品风味与创建构建类型类似:只需将它们添加到 productFlavors {} 代码块并配置您想要的设置。产品风味支持与 defaultConfig 相同的属性,这是因为 defaultConfig 实际上属于 ProductFlavor 类。这意味着,您可以在 defaultConfig {} 代码块中提供所有风味的基本配置,每种风味均可更改任何这些默认值,例如 applicationId。要详细了解应用 ID,请阅读设置应用 ID

注:您仍需在 main/ 清单文件中使用 package 属性指定程序包名称。您还必须在源代码中使用此程序包名称引用 R 类或者解析任何相关的 Activity 或服务注册。这样,您可以使用 applicationId 为每个产品风味分配一个唯一的 ID,以用于打包和分发,而不必更改您的源代码。
1
1
 
1
注:您仍需在 main/ 清单文件中使用 package 属性指定程序包名称。您还必须在源代码中使用此程序包名称引用 R 类或者解析任何相关的 Activity 或服务注册。这样,您可以使用 applicationId 为每个产品风味分配一个唯一的 ID,以用于打包和分发,而不必更改您的源代码。

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.
2
2
 
1
Error:All flavors must now belong to a named flavor dimension.
2
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.
1
1
 
1
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。
1
1
 
1
注:要利用 Google Play 中的 Multiple APK Support 分发您的应用,请为所有变体分配相同的 applicationId 值并为每个变体分配一个不同的 versionCode。要在 Google Play 中以独立应用的形式分发应用的不同变体,您需要为每个变体分配一个不同的 applicationId。
在创建和配置您的产品风味之后,在通知栏中点击   Sync Now。在同步完成后,Gradle 会根据您的构建类型和产品风味自动创建构建变体 [ build variants ],并按照   <product-flavor><Build-Type>  的格式命名这些变体。例如,如果您创建了“demo”和“full”这两种产品风味并保留默认的“debug”和“release”构建类型,Gradle 将创建以下构建变体[build variants]:
demoDebug   demoRelease   fullDebug   fullRelease
1
1
 
1
demoDebug   demoRelease   fullDebug   fullRelease

您可以将构建变体更改为您要构建并运行的任何变体,只需转到 Build > Select Build Variant,然后从下拉菜单中选择一个变体。然而,要开始自定义每个构建变体及其功能和资源,您需要了解如何创建和管理源集

组合多个产品风味

Combine multiple product flavors with flavor dimensions

某些情况下,您可能希望组合多个产品风味中的配置。例如,您可能希望基于 API 级别为“full”和“demo”产品风味创建不同的配置。为此,您可以通过适用于 Gradle 的 Android 插件创建产品风味组,称为风味维度[flavor dimensions]。构建您的应用时,Gradle 会将您定义的每个风味维度中的产品风味配置与构建类型配置组合来创建最终构建变体。Gradle 不会组合属于相同风味维度的产品风味。

提示:要根据 ABI 和屏幕密度创建不同版本的应用,您应 build multiple APKs,而不是使用产品风味。
1
1
 
1
提示:要根据 ABI 和屏幕密度创建不同版本的应用,您应 build multiple APKs,而不是使用产品风味。

下面的代码示例使用 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. */
24
      versionCode 30000 + android.defaultConfig.versionCode
25
      versionNameSuffix "-minApi24"
26
    }
27
28
    minApi23 {
29
      dimension "api"
30
      minSdkVersion '23'
31
      versionCode 20000  + android.defaultConfig.versionCode
32
      versionNameSuffix "-minApi23"
33
    }
34
35
    minApi21 {
36
      dimension "api"
37
      minSdkVersion '21'
38
      versionCode 10000  + android.defaultConfig.versionCode
39
      versionNameSuffix "-minApi21"
40
    }
41
  }
42
}
43
...

Gradle 创建的构建变体数量等于每个风味维度中的风味数量与您配置的构建类型数量的乘积。在 Gradle 为每个构建变体或对应 APK 命名时,属于较高优先级风味维度的产品风味首先显示,之后是较低优先级维度的产品风味,再之后是构建类型。以上面的构建配置为例,Gradle 可以使用以下命名方案创建总共 12 个构建变体:

Build variant: [minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
Corresponding APK: app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
2
2
 
1
Build variant: [minApi24, minApi23, minApi21][Demo, Full][Debug, Release]
2
Corresponding APK: app-[minApi24, minApi23, minApi21]-[demo, full]-[debug, release].apk
例如:
Build variant: minApi24DemoDebug
Corresponding APK: app-minApi24-demo-debug.apk
2
2
 
1
Build variant: minApi24DemoDebug
2
Corresponding APK: app-minApi24-demo-debug.apk

除了可以为各个产品风味和构建变体创建源集目录外,您也可以为每个产品风味组合创建源集目录。例如,您可以创建 Java 源并将其添加到 src/demoMinApi24/java/ 目录中,Gradle 仅会在构建组合了这两种产品风味的变体时使用这些源。与属于各个产品风味的源集相比,您为产品风味组合创建的源集拥有更高的优先级。要详细了解源集和 Gradle 如何合并源,请阅读有关如何创建源集的部分。

过滤变体

Filter variants

Gradle 会为您配置的产品风味与构建类型的每个可能的组合创建构建变体。不过,某些特定的构建变体在您的项目环境中并不必要,也可能没有意义。您可以在模块级 build.gradle 文件中创建一个变体过滤器[variant filter],以移除某些构建变体配置。

以上一部分中的构建配置为例,假设您计划为 demo 版本的应用仅支持 API levels 23 和更高级别。您可以使用 variantFilter {} 代码块过滤出组合了“minApi21”和“demo”产品风味的所有构建变体配置:

android {
  buildTypes {...}
  flavorDimensions "api", "mode"
  productFlavors {
    demo {...}
    full {...}
    minApi24 {...}
    minApi23 {...}
    minApi21 {...}
  }

  variantFilter { variant ->
      def names = variant.flavors*.name
      // To check for a certain build type, use variant.buildType.name == "<buildType>"
      if (names.contains("minApi21") && names.contains("demo")) {
          setIgnore(true)  // Gradle ignores any variants that satisfy满足 the conditions above.
      }
  }
}
19
19
 
1
android {
2
  buildTypes {...}
3
  flavorDimensions "api", "mode"
4
  productFlavors {
5
    demo {...}
6
    full {...}
7
    minApi24 {...}
8
    minApi23 {...}
9
    minApi21 {...}
10
  }
11
12
  variantFilter { variant ->
13
      def names = variant.flavors*.name
14
      // To check for a certain build type, use variant.buildType.name == "<buildType>"
15
      if (names.contains("minApi21") && names.contains("demo")) {
16
          setIgnore(true)  // Gradle ignores any variants that satisfy满足 the conditions above.
17
      }
18
  }
19
}

在您向构建配置添加变体过滤器并点击通知栏中的 Sync Now 后,Gradle 将忽略满足您指定的条件的任何构建变体,在您点击菜单栏中的 Build > Select Build Variant(或工具窗口栏中的 Build Variants构建 build variants 构建变体)时,这些构建变体将不会再显示在下拉菜单中。

创建源集

Create source sets

默认情况下,Android Studio 会创建 main/ 源集和目录,用于存储您要在所有构建变体之间共享的一切资源。然而,您可以创建新的源集来控制 Gradle 要为特定的构建类型、产品风味(以及使用风味维度时的产品风味组合)和构建变体编译和打包的确切文件。例如,您可以在 main/ 源集中定义基本的功能,使用产品风味源集针对不同的客户更改应用的品牌,或者仅针对使用调试构建类型的构建变体包含特殊的权限和日志记录功能

Gradle 要求您按照与 main/ 源集类似的特定方式组织源集文件和目录。例如,Gradle 要求您的“debug”构建类型所特定的 Java 类文件位于 src/debug/java/ 目录中。

适用于 Gradle 的 Android 插件提供了一项有用的 Gradle 任务,可向您展示如何针对每种构建类型、产品风味和构建变体组织您的文件。例如,报告的以下部分描述了 Gradle 要求在何处能找到“调试”构建类型的特定文件:

------------------------------------------------------------
Project :app
------------------------------------------------------------
...
debug
----
Compile configuration: compile
build.gradle name: android.sourceSets.debug
Java sources: [app/src/debug/java]
Manifest file: app/src/debug/AndroidManifest.xml
Android resources: [app/src/debug/res]
Assets: [app/src/debug/assets]
AIDL sources: [app/src/debug/aidl]
RenderScript sources: [app/src/debug/rs]
JNI sources: [app/src/debug/jni]
JNI libraries: [app/src/debug/jniLibs]
Java-style resources: [app/src/debug/resources]
17
 
1
------------------------------------------------------------
2
Project :app
3
------------------------------------------------------------
4
...
5
debug
6
----
7
Compile configuration: compile
8
build.gradle name: android.sourceSets.debug
9
Java sources: [app/src/debug/java]
10
Manifest file: app/src/debug/AndroidManifest.xml
11
Android resources: [app/src/debug/res]
12
Assets: [app/src/debug/assets]
13
AIDL sources: [app/src/debug/aidl]
14
RenderScript sources: [app/src/debug/rs]
15
JNI sources: [app/src/debug/jni]
16
JNI libraries: [app/src/debug/jniLibs]
17
Java-style resources: [app/src/debug/resources]

要为您的构建配置生成和查看此报告,请继续如下操作:

  • 点击 IDE 窗口右侧的 Gradle 构建 build variants 构建变体 
  • 导航至 MyApplication > Tasks > android 并双击 sourceSets。After Gradle executes the task, the Run window should then open to display the output.
  • If the display is not in text mode as shown above, click Toggle view 构建 build variants 构建变体 on the left side of the Run window.
构建 build variants 构建变体
注:此报告还向您展示了如何为您希望用来运行应用测试的文件组织源集,例如 test/ 和 androidTest/ 测试源集。
1
注:此报告还向您展示了如何为您希望用来运行应用测试的文件组织源集,例如 test/  androidTest/ 测试源集。

当您创建新的构建变体时,Android Studio 不会为您创建源集目录,但会为您提供几个选项,帮助您创建。例如,要为“debug”构建类型只创建 java/ 目录,请执行以下操作:

  • 打开 Project 窗格并从窗格顶端的下拉菜单中选择 Project 视图。
  • 导航至 MyProject/app/src/
  • 右键点击 src 目录并选择 New > Folder > Java Folder
  •  Target Source Set 旁边的下拉菜单中,选择 debug
  • 点击 Finish

Android Studio 将会为您的调试构建类型创建源集目录,然后在该目录内部创建 java/ 目录。或者,在针对特定的构建变体向您的项目中添加新文件时,您也可以让 Android Studio 为您创建目录。例如,要为“debug”构建类型创建 XML 值文件:

  • 在相同的 Project 窗格中,右键点击 src 目录并选择 New > XML > Values XML File
  • 为 XML 文件输入名称或保留默认名称。
  •  Target Source Set 旁边的下拉菜单中,选择 debug
  • 点击 Finish

由于“debug”构建类型被指定为目标源集,Android Studio 会在创建 XML 文件时自动创建必要的目录。最终的目录结构看上去应该类似于图 2。

构建 build variants 构建变体

图 2. debug构建类型的新源集目录。

按照同样的方法,您还可以为产品风味创建源集目录(例如 src/demo/),为构建变体创建源集目录(例如 src/demoDebug/)。此外,您还可以创建针对特定构建变体的测试源集,例如 src/androidTestDemoDebug/。如需了解更多信息,请转至测试源集

更改默认源集配置

Change default source set configurations

如果您的 sources 未组织到 Gradle 期望的默认源集文件结构中(如上面的创建源集部分中所述),您可以使用 sourceSets {}代码块更改 Gradle 希望为源集的每个组件收集文件的位置。您不需要重新定位文件;只需要为 Gradle 提供相对于模块级 build.gradle 文件的路径,Gradle 应当可以在此路径下为每个源集组件找到文件。要了解您可以配置哪些组件,以及是否可以将其映射到多个文件或目录,请阅读适用于 Gradle 的 Android 插件参考

下面的代码示例可以将 app/other/ 目录中的源映射到 main 源集的某些组件,并更改 androidTest 源集的根目录。

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. */
18
      setRoot 'src/tests'
19
    }
20
  }
21
}

使用源集构建

Build with source sets

您可以使用源集目录包含您希望仅针对某些配置打包的代码和资源。例如,如果您要构建“demoDebug”构建变体(它是“demo”产品风味和“debug”构建类型的合体),Gradle 会查看这些目录并赋予以下优先级顺序:

  • src/demoDebug/   (build variant source set)
  • src/debug/   (build type source set)
  • src/demo/   (product flavor source set)
  • src/main/   (main source set)

注:如果您 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,以此类推。此外,与属于各个产品风味的源集相比,您为产品风味组合创建的源集拥有更高的优先级。
x
 
1
注:如果您 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,以此类推。此外,与属于各个产品风味的源集相比,您为产品风味组合创建的源集拥有更高的优先级。

上面列出的顺序决定了在 Gradle 合并代码和资源时哪个源集具有较高的优先级。由于   demoDebug/   源集目录很可能包含特定于该构建变体的文件,如果   demoDebug/   包含在   debug/   中也有定义的文件,Gradle 将使用   demoDebug/   源集中的文件。同样,Gradle 会为构建类型和产品风味源集中的文件赋予比   main/   中相同文件更高的优先级。Gradle 在应用以下构建规则时会考虑此优先级顺序:

  • All source code in the java/ directories are compiled together to generate a single output.
注:对于给定的构建变体,如果找到两个或两个以上定义同一 Java 类的源集目录,Gradle 就会引发一个构建错误。例如,在构建调试 APK 时,您不能同时定义 src/debug/Utility.java 和 src/main/Utility.java。这是因为 Gradle 会在构建过程中检查这两个目录并引发“duplicate class”错误。如果针对不同的构建类型需要不同版本的 Utility.java,您可以让每个构建类型定义其自己的文件版本,而不将其包含在 main/ 源集中。
 
1
注:对于给定的构建变体,如果找到两个或两个以上定义同一 Java 类的源集目录,Gradle 就会引发一个构建错误。例如,在构建调试 APK 时,您不能同时定义 src/debug/Utility.java  src/main/Utility.java。这是因为 Gradle 会在构建过程中检查这两个目录并引发“duplicate class”错误。如果针对不同的构建类型需要不同版本的 Utility.java,您可以让每个构建类型定义其自己的文件版本,而不将其包含在 main/ 源集中。
  • Manifests are merged together into a single manifest.  将按照上述列表中的相同顺序指定优先级。也就是说,某个构建类型的清单设置会替换某个产品风味的清单设置,依此类推。如需了解更多信息,请阅读合并清单
  • 同样,values/ 目录中的文件也会合并在一起。如果两个文件同名,例如存在两个 strings.xml 文件,将按照上述列表中的相同顺序指定优先级。也就是说,在构建类型源集中的文件中定义的值将会替换产品风味中同一文件中定义的值,依此类推。
  • res/  asset/ 目录中的资源将打包到一起。如果两个或两个以上的源集中定义有同名资源,将按照上述列表中的相同顺序指定优先级。
  • 最后,在构建 APK 时,Gradle 会为随库模块依赖项包含的资源和清单分配最低的优先级。

声明依赖项

Declare dependencies
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
    freeImplementation project(":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.
5
}

For more information, see Add build dependencies.

配置签署设置

Configure signing settings

除非您为发布构建显式定义签署配置,否则,Gradle 不会签署发布构建的 APK。您可以轻松创建发布密钥并使用 Android Studio 签署发布构建类型

要使用 Gradle 构建配置为您的发布构建类型手动配置签署配置:

  • Create a keystore。密钥库[keystore ]是一个二进制文件,它包含一组私钥[a set of private keys]。您必须将密钥库存放在安全可靠的地方。
  • Create a private key。私钥[private key]代表将通过应用识别的实体[the entity to be identified with the app],如某个人或某家公司。
  • 将签署配置添加到模块级 build.gradle 文件中:
android {
    defaultConfig {...}
    signingConfigs {
        release {
            storeFile file("myreleasekey.keystore")
            storePassword "password"
            keyAlias "MyReleaseKey"
            keyPassword "password"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
}
1
android {
2
    defaultConfig {...}
3
    signingConfigs {
4
        release {
5
            storeFile file("myreleasekey.keystore")
6
            storePassword "password"
7
            keyAlias "MyReleaseKey"
8
            keyPassword "password"
9
        }
10
    }
11
    buildTypes {
12
        release {
13
            signingConfig signingConfigs.release
14
        }
15
    }
16
}

要生成签署的 APK,请从菜单栏中选择 Build > Generate Signed APK。The package in app/build/apk/app-release.apk is now signed with your release key。

注:将发布密钥和密钥库的密码放在构建文件中并不安全。作为替代方案,您可以将此构建文件配置为通过环境变量获取这些密码,或让构建流程提示您输入这些密码。
1
注:将发布密钥和密钥库的密码放在构建文件中并不安全。作为替代方案,您可以将此构建文件配置为通过环境变量获取这些密码,或让构建流程提示您输入这些密码。

要通过环境变量[environment variables]获取这些密码:

storePassword System.getenv("KSTOREPWD")
keyPassword System.getenv("KEYPWD")
2
2
1
storePassword System.getenv("KSTOREPWD")
2
keyPassword System.getenv("KEYPWD")

要让构建流程在您要从命令行调用此构建时提示您输入这些密码:

storePassword System.console().readLine("\nKeystore password: ")
keyPassword System.console().readLine("\nKey password: ")
2
1
storePassword System.console().readLine("\nKeystore password: ")
2
keyPassword System.console().readLine("\nKey password: ")

在完成此流程后,您可以分发您的应用并在 Google Play 上发布它。

警告:将密钥库和私钥存放在安全可靠的地方,并确保您为其创建了安全的备份。如果您将应用发布到 Google Play,随后丢失了您用于签署应用的密钥,那么,您将无法向您的应用发布任何更新,因为您必须始终使用相同的密钥签署应用的所有版本。
1
警告:将密钥库和私钥存放在安全可靠的地方,并确保您为其创建了安全的备份。如果您将应用发布到 Google Play,随后丢失了您用于签署应用的密钥,那么,您将无法向您的应用发布任何更新,因为您必须始终使用相同的密钥签署应用的所有版本。


签署 Android Wear 应用

Signing Wear OS apps

发布 Android Wear 应用时,请将穿戴式设备应用打包到手持类应用中,因为用户无法直接在穿戴式设备上浏览和安装应用。这两个应用均必须进行签署。如需有关打包和签署 Android Wear 应用的更多信息,请参阅打包穿戴式设备应用


2018-7-22