使用 build 变体创建不同版本的应用

1. 简介

上次更新日期:2022 年 4 月 14 日

build 变体有助于创建应用的不同版本。例如,您可能想为应用构建两个版本,一个是内容有限的免费版本,另一个是包含更多内容的付费版本。您还可以根据 API 级别或其他设备变化因素,为应用构建以不同设备为目标的不同版本。

在此 Codelab 中,您将修改在第 1 单元:Kotlin 基础知识中创建的 Dice Roller 应用,使它有两个版本:“demo”和“full”。“full”版本包含一个额外的文本框,其中会以字词形式显示掷骰子的结果,因此用户无需仅凭骰子图片来获取掷骰子的结果。

您应当已掌握的内容

您应该:

  • 已学完第 1-4 课的“Android 基础知识”学习在线课程。如需学习必要的 Codelab,请参阅第 1 单元:Kotlin 基础知识在线课程。
  • 大致了解 Android 构建系统。如需熟悉其主要组件,请查看构建概览

学习内容

  • 什么是 build 变体。
  • 什么是源代码集。
  • 如何使用 build 变体和源代码集构建不同版本的应用。
  • 如何为应用变体提供唯一的应用 ID。

构建内容

在此 Codelab 中,您将从在第 1 单元:Kotlin 基础知识学习在线课程中构建的 DiceRoller 应用开始构建。DiceRoller 应用包含一张骰子图片,其下方显示了一个 ROLL 按钮。当用户点击 ROLL 时,骰子会掷出,图片也会根据掷骰子的结果而变化。

您将创建其他项目文件并添加代码,以便实现以下目标:

  • 为您的应用创建“demo”和“full”产品变种。
  • 创建与产品变种对应的“demo”和“full”源代码集。
  • 向“full”版本的应用布局添加一个框。
  • 对“full”版本的框进行编程,以便在用户点击 ROLL 时显示掷骰子的结果。
  • 自定义“demo”和“full”应用版本的应用名称。
  • 为“demo”和“full”应用版本提供唯一应用 ID。

应用的“full”版本将如下所示:

包含动态框的 DiceRoller 应用。

所需条件

2. 设置您的环境

获取代码

如果您没有通过“第 1 单元:Kotlin 基础知识”获取完成后的 DiceRoller 应用,请从 GitHub 下载应用代码

如需下载应用代码并在 Android Studio 中打开,请按以下步骤操作:

  1. android-basics-kotlin-dice-roller-with-images-app-solution GitHub 代码库首页中,依次点击 Code > Download ZIP
  2. 下载 ZIP 文件后,在 Android Studio 中打开项目,然后依次点击 File > Open。您可以启动空 activity,或在出现提示时打开先前的项目。怎么都没关系,因为我们将打开下载的项目。
  3. 找到 ZIP 文件下载到的位置(可能是您的 Downloads 文件夹),选择该文件,然后点击 Open

使用 Project 视图

处理 build 变体时,您需要在 Project 视图中处理您的项目文件,以查看不同变体的所有目录。为此,请在 Android Studio 中打开 Project 窗格,点击视图类型菜单(默认设为 Android 视图),然后选择 Project 视图。

3. 了解 build 变体

build 变体是以不同方式组合产品变种和 build 类型的产物。您可以将产品变种视为主要面向用户的属性,并将 build 类型视为主要面向开发者的属性。实际上,您并不直接配置 build 变体;相反,您可以配置一组产品变种和一组 build 类型,进而决定 build 变体。

具体而言,build 变体代表产品变种和 build 类型的每个组合,并相应地命名为 <product-flavor><build-type>。例如,如果您的 build 类型为 debugrelease 且产品变种为 demofull,则生成的 build 变体如下:

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease

我们来为 DiceRoller 应用配置产品变种和 build 类型。

4. 配置产品变种

产品变种是主要面向用户的应用属性,因为它们通常代表可供用户使用的应用版本。如需创建“demo”和“full”版本的应用,您必须添加两个产品变种并将其分配到一个变种维度。如需添加产品变种,请打开应用级 build.gradle 文件(Project 视图中的 app > build.gradle),然后将以下代码粘贴到 android {} 代码块中。

flavorDimensions "app_type"
productFlavors {
   demo {
       dimension "app_type"
         }
   full {
       dimension "app_type"
   }
}

此代码将执行以下操作:

  • 创建名为 app_type 的变种维度。
  • 创建两个以 demo {}full {} 代码块代表的产品变种。
  • 将两个产品变种分配到 app_type 维度(如果只有一个变种维度,此项为可选操作)。

这是定义产品变种所需的基本代码。稍后,您会在此 Codelab 中使用一些其他选项。

5. 配置 build 类型

build 类型是主要面向开发者的应用属性,因为它们通常代表开发阶段(例如调试、Beta 版和发布)。Android Studio 会自动为您配置两个 build 类型:debugreleasedebug build 类型用于调试,而 release build 类型用于分发。

您可以通过修改应用级 build.gradle 文件中的 buildTypes {} 代码块来创建 build 类型并修改其配置。默认的 buildTypes {} 代码块如下所示:

buildTypes {
   release {
       minifyEnabled false
       proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
   }
}

您可以看到 release build 类型的默认配置(我们不会在此 Codelab 中介绍 minifyEnabledproguardFiles 属性)。默认情况下,debug build 类型不会出现在 build 配置文件中,但您可以添加 debug {} 代码块来添加或更改某些设置。默认配置可满足我们的需求,因此可以保持不变。

6. 使用“Build Variants”工具窗口

现在您拥有了两个产品变种和两个 build 类型,接下来我们就看看它们能创建出哪些 build 变体。如需在 Android Studio 中查看新的 build 变体,请执行以下操作:

  1. 点击工具栏中的 Sync Project with Gradle Files 图标 4e7fbf18152549d8.png。每当您对 build 配置文件进行更改时,Studio 都会提示您同步文件,以便其保存新的 build 配置并检查是否存在 build 错误。
  2. 依次点击 Build > Select Build Variant(或依次点击 View > Tool Windows > Build Variants),以显示 Build Variants 窗口。
  3. 点击 Active Build Variant 列中的 demoDebug,打开包含所有 build 变体的菜单:demoDebug、demoRelease、fullDebugfullRelease。使用该菜单选择要运行和测试的不同 build 变体。

显示“Active Build Variant”菜单的“Build Variants”工具窗口。

运行 demoDebugfullDebug 变体(基于 release build 类型的变体需要更多设置才能运行,因此我们在此 Codelab 中不做介绍)。到目前为止,对于用户来说,demoDebugfullDebug 变体是无法区分的。

7. 为不同的变体创建不同的功能

现在您已拥有“demo”和“full”版本的应用,接下来让我们向“full”版本添加一些功能。

使用源代码集添加高级功能

对于 full 产品变种,我们将添加一个用于显示掷骰子结果的框,这样用户就不必仅凭骰子图片来了解掷骰子的结果了。如需添加此高级功能,请使用源代码集。源代码集是一种目录,其中包含特定 build 类型、产品变种和 build 变种的内容。默认的 main 源代码集 (app > src > main) 包含要在所有 build 变体之间共享的内容。此默认内容可被其他源代码集中的内容替换。

如何替换 main 源代码集中的内容并确定需要添加的源代码集,取决于您要更改的内容。

如需更改资源,例如布局或图片(main > res 中的内容),请按以下常规步骤操作:

  1. 为要更改的产品变种创建源代码集(或目录)(我们将在下一部分中介绍创建此源代码集的位置和方式)。
  2. 将要更改的资源文件粘贴到这个新的源代码集中,然后对其进行更新。当 Android Gradle 插件 (AGP) 构建依赖于新源代码集的 build 变体时,它会将 main 中的资源代码替换为新源代码集中的资源代码。

如需替换 Java 或 Kotlin 类中的行为(main > java 中的内容),请按以下常规步骤操作:

  1. 为要更改的产品变种以及同一变种维度中的所有其他产品变种创建源代码集(或目录)。
  2. 将要更改的文件粘贴到所有产品变种源代码集中,然后修改要更改的副本。
  3. main 源代码集中删除原始文件。

如需向应用的“full”版本添加动态框,最好将高级功能视为两项主要修改:

  • 自定义布局:通过修改 activity_main.xml 文件添加一个框。
  • 自定义应用的行为:通过修改 MainActivity.kt 文件,根据掷骰子的结果更改框中显示的内容。

在下一部分中,您将了解创建源代码集的位置和方式。

确定在哪里创建新的源代码集

Android Gradle 插件 (AGP) 会向您展示如何组织每个 build 类型、产品变种和 build 变体的文件。如需向 full 产品变种添加包含对 MainActivity.kt 文件的更改的高级功能,您要为 fulldemo 变种创建源代码集。如需确定创建这些源代码集的位置,请在 Android Studio 中执行以下步骤:

  1. 点击 IDE 窗口中的 Gradle
  2. 依次进入 MyApplication > Tasks > android,然后双击 sourceSets。如果您未看到 Tasks 文件夹,请依次点击 File > Settings > Experimental 并取消选中 Do not build Gradle task list during Gradle sync(在 macOS 上,依次点击 Android Studio > Preferences > Experimental)。Gradle 执行该任务后,Run 窗口应随即显示输出。
  3. 如果显示内容不是处于此处所示的文本模式,请点击 Run 窗口中的 Toggle view 图标 82487fd4e011f105.png

Run 窗口中,您应该会看到以下输出:

------------------------------------------------------------
Project ':app'
------------------------------------------------------------

...

debug
-----
Compile configuration: debugCompile
build.gradle name: android.sourceSets.debug
Java sources: [app/src/debug/java]
Kotlin sources: [app/src/debug/kotlin, 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]

...

full
----
Compile configuration: fullCompile
build.gradle name: android.sourceSets.full
Java sources: [app/src/full/java]
Kotlin sources: [app/src/full/kotlin, app/src/full/java]
Manifest file: app/src/full/AndroidManifest.xml
Android resources: [app/src/full/res]
Assets: [app/src/full/assets]
AIDL sources: [app/src/full/aidl]
RenderScript sources: [app/src/full/rs]
JNI sources: [app/src/full/jni]
JNI libraries: [app/src/full/jniLibs]
Java-style resources: [app/src/full/resources]

“debug”下的文件路径列表描述了在默认情况下,AGP 会在何处查找“debug”产品变种的应用代码和资源。同样,“full”下的文件路径列表描述了在默认情况下,AGP 会在何处查找“full”产品变种的内容。

请注意“Java sources”(针对 Java 和 Kotlin 类等文件)和“Android resources”(针对布局和图片等文件)文件路径。现在您已了解了创建新源代码集的位置,接下来就可以创建这些源代码集并为高级功能添加代码了。

自定义“full”版本的布局

如需向应用的“full”版本添加框,请按以下步骤操作:

首先,创建 full 源代码集和 Java 资源目录:

  1. 打开 Project 窗格,然后选择 Project 视图。
  2. 进入 DiceRoller/app/src/ 目录。
  3. 右键点击 src 目录,然后依次选择 New > Directory
  4. Gradle Source Sets 下的菜单中,选择 full/resources,然后按 Enter

然后,将 main 源代码集中的 activity_main.xml 文件粘贴到 full 源代码集中。

  1. 进入 DiceRoller/app/src/main/res/
  2. 右键点击 activity_main.xml 文件,然后点击 Copy
  3. 进入 DiceRoller/app/src/full/res/
  4. 右键点击 res 目录,然后点击 Paste

接下来,如需为应用的 full 变种添加框,请将以下代码添加到 full 源代码集中的 activity_main.xml 文件:

<TextView
    android:id="@+id/resultTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="16sp"
    android:text="Result"
    app:layout_constraintBottom_toTopOf="@+id/button"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/imageView" />

运行应用的 fullDebugdemoDebug build 变体(使用 Build Variants 工具窗口选择要运行的 build 变体,然后点击 Run)。您应该只会看到 fullDebug 变体的新框。由于该框目前还无法执行任何操作,因此我们要对其进行编程,使其能够根据掷骰子的结果而更改。

包含显示“Result”作为占位符的框的 DiceRoller 应用。

自定义“full”版本的行为

对于“full”版本的应用,该框应使用字词来显示掷骰子的结果。如需对该行为进行编程,请按以下步骤操作:

首先,创建 full 源代码集 Java 源代码目录。

  1. 通过 Project 视图中的 Project 窗格,进入 DiceRoller/app/src/full 目录。
  2. 右键点击 full 目录,然后依次选择 New > Directory
  3. Gradle Source Sets 菜单中,选择 java,然后按 Enter

然后,创建 debug 源代码集和 Java 源代码目录。

  1. 通过 Project 视图中的 Project 窗格,进入 DiceRoller/app/src 目录。
  2. 右键点击 src 目录,然后依次选择 New > Directory
  3. Gradle Source Sets 菜单中,选择 debug/java,然后按 Enter

接下来,进入 DiceRoller/app/src/main/java 目录。

  1. MainActivity.kt 文件粘贴到 full/javadebug/java 目录中。
  2. 从主源代码集中删除 java 目录(包括 MainActivity.kt 文件)。(右键点击 java 目录,然后点击 Delete。)
  3. 在“full”源代码集 MainActivity.kt 文件中,将以下代码添加到 rollDice() 方法:
// Update the result text view
val resultTextView: TextView = findViewById(R.id.resultTextView)
resultTextView.text = when (diceRoll) {
    1 -> "One"
    2 -> "Two"
    3 -> "Three"
    4 -> "Four"
    5 -> "Five"
    else -> "Six"
}

再次运行 fullDebugdemoDebug build 变体。“full”版本中的框应包含掷骰子的结果。

包含动态框的 DiceRoller 应用。

更改应用名称

为清楚起见,我们要在应用名称中指定您当前使用的应用版本。这种类型的更改实际上无需源代码集即可完成。应用名称由 AndroidManifest.xml 文件中的 label 属性定义 (app > manifests > AndroidManifest.xml)。如需让 label 值根据正在运行的变体而更改,请打开 AndroidManifest.xml 文件并将标签行更改为以下代码:

android:label="${appLabel}"

这会分配变量 appLabel 作为应用名称。

接下来,如需设置 appLabel 的值或更改应用的“demo”版本的名称,请将 manifestPlaceholders 代码行添加到您之前创建的 demo {} 代码块中:

demo {
   dimension "version"
   manifestPlaceholders = [appLabel: "Dice Roller - Demo"]
   applicationIdSuffix ".demo"
}

同样,如需更改应用的 full 变种的名称,请将另一个 manifestPlaceholders 代码行添加到 full {} 代码块中:

full {
   dimension "version"
   manifestPlaceholders = [appLabel: "Dice Roller - Full"]
   applicationIdSuffix ".full"
}

现在,再次运行 demoDebugfullDebug 变体。现在,您应该会看到不同的 build 变体已具有不同的名称。

完成后的包含动态框的 DiceRoller 应用。

8. 为 build 变体提供唯一应用 ID

当您为应用构建 APK 或 AAB 时,构建工具会使用应用级 build.gradle 文件的 defaultConfig {} 代码块中定义的应用 ID 标记应用(如下所示)。不过,如果您要创建不同版本的应用,让其在 Google Play 商店中显示为单独的详情(如“demo”和“full”版本),则需要为每个版本提供不同的应用 ID。对于 productFlavors {} 代码块中的每个变种,您可以重新定义 applicationId 属性,也可以使用 applicationIdSuffix 在默认的应用 ID 上追加一段,如下所示:

defaultConfig {
   applicationId "com.example.diceroller"
   ...
}

flavorDimensions "version"
productFlavors {
   demo {
 dimension "version"
       manifestPlaceholders = [appLabel: "Dice Roller - Demo"]
         applicationIdSuffix ".demo"
   }
   full {
       dimension "version"
       manifestPlaceholders = [appLabel: "Dice Roller - Full"]
         applicationIdSuffix ".full"
   }
}

9. 恭喜

恭喜!您已成功使用 build 变体构建了两个版本的 DiceRoller 应用!

您配置了产品变种和 build 类型来创建 build 变体。您使用源代码集向“full”应用版本添加了一项高级功能。您学习了如何为每个 build 变体提供唯一应用 ID,以便在 Play 商店中将二者视为单独的应用。

现在,您已了解通过哪些基本步骤,可以创建多个应用版本,以便更好地服务于不同的用户群组。

接下来做什么?

参考文档