配置构建

Android 构建系统会编译应用资源和源代码,并将其打包成 APK 或 Android App Bundle,以便您进行测试、部署、签名和分发。

Gradle 构建概览 Android 构建结构中,我们讨论了构建概念和 Android 应用的结构。现在是时候配置构建了。

Android 构建术语表

Gradle 和 Android Gradle 插件可帮助您配置构建的以下方面

构建类型 (Build types)

构建类型定义了 Gradle 在构建和打包应用时使用的某些属性。构建类型通常针对开发生命周期的不同阶段进行配置。

例如,debug 构建类型会启用调试选项并使用调试密钥对应用进行签名,而 release 构建类型可能会对应用进行缩减、混淆,并使用发布密钥进行签名以便分发。

您必须至少定义一种构建类型才能构建应用。Android Studio 默认会创建 debug 和 release 构建类型。要开始自定义应用的打包设置,请了解如何配置构建类型

产品风味 (Product flavors)
产品风味代表您可以向用户发布的不同版本的应用,例如免费版和付费版。您可以自定义产品风味以使用不同的代码和资源,同时共享和重用所有应用版本通用的部分。产品风味是可选的,您必须手动创建它们。要开始创建应用的不同版本,请了解如何配置产品风味
构建变体
构建变体 (Build variant) 是构建类型和产品风味的组合,是 Gradle 用于构建应用的配置。通过使用构建变体,您可以在开发过程中构建产品风味的调试版本,以及用于分发的产品风味的签名发布版本。虽然您不会直接配置构建变体,但您可以配置构成它们的构建类型和产品风味。创建额外的构建类型或产品风味也会创建额外的构建变体。要了解如何创建和管理构建变体,请阅读配置构建变体概览。
清单条目
您可以在构建变体配置中为清单文件 (manifest file) 的某些属性指定值。这些构建值会覆盖清单文件中现有的值。如果您想生成应用的不同变体(具有不同的应用名称、最低 SDK 版本或目标 SDK 版本),这非常有用。当存在多个清单文件时,清单合并工具会合并清单设置
依赖项
构建系统会管理来自本地文件系统和远程存储库的项目依赖项。这意味着您不必手动搜索、下载并将依赖项的二进制包复制到您的项目目录中。欲了解更多信息,请参阅添加构建依赖项
签名
构建系统允许您在构建配置中指定签名设置,并可以在构建过程中自动为您的应用签名。构建系统使用已知的凭据,通过默认密钥和证书对调试版本进行签名,以避免在构建时出现密码提示。除非您明确为此构建定义了签名配置,否则构建系统不会对发布版本进行签名。如果您没有发布密钥,可以按照为您的应用签名中的说明生成一个。通过大多数应用商店分发应用时,必须使用已签名的发布版本。
代码和资源缩减
构建系统允许您为每个构建变体指定不同的 ProGuard 规则文件。在构建应用时,构建系统会使用其内置的缩减工具(例如 R8)应用相应的规则集来缩减您的代码和资源。缩减代码和资源有助于减小 APK 或 AAB 的体积。
多 APK 支持
构建系统允许您自动构建多个 APK,每个 APK 仅包含特定屏幕密度或应用程序二进制接口 (ABI) 所需的代码和资源。有关更多信息,请参阅构建多个 APK。不过,建议的做法是发布单个 AAB,因为它除了按屏幕密度和 ABI 分割外,还提供按语言分割的功能,同时避免了需要向 Google Play 上传多个工件的问题。2021 年 8 月之后提交的所有新应用都必须使用 AAB。

Android 构建中的 Java 版本

无论您的源代码是使用 Java、Kotlin 编写的,还是两者混用,在构建时都有几个地方需要您选择 JDK 或 Java 语言版本。有关详情,请参阅Android 构建中的 Java 版本

构建配置文件

创建自定义构建配置需要对一个或多个构建配置文件进行更改。这些纯文本文件使用领域特定语言 (DSL) 来描述和操作构建逻辑,使用的是 Kotlin 脚本(Kotlin 语言的一种变体)。您也可以使用 Groovy(一种用于 Java 虚拟机 (JVM) 的动态语言)来配置构建。

您无需了解 Kotlin 脚本或 Groovy 即可开始配置构建,因为 Android Gradle 插件引入了您所需的大部分 DSL 元素。要了解有关 Android Gradle 插件 DSL 的更多信息,请阅读DSL 参考文档。Kotlin 脚本也依赖于底层的 Gradle Kotlin DSL

启动新项目时,Android Studio 会自动为您创建其中一些文件,并根据合理的默认值进行填充。有关所创建文件的概览,请参阅 Android 构建结构

Gradle Wrapper 文件

Gradle Wrapper (gradlew) 是随源代码一起提供的一个小型应用程序,用于下载和启动 Gradle 本身。这可以确保构建执行的一致性。开发人员下载应用程序源代码并运行 gradlew,它会下载所需的 Gradle 发行版并启动 Gradle 来构建您的应用程序。

gradle/wrapper/gradle-wrapper.properties 文件包含一个属性 distributionUrl,它描述了用于运行构建的 Gradle 版本。

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Gradle 设置文件

settings.gradle.kts 文件(针对 Kotlin DSL)或 settings.gradle 文件(针对 Groovy DSL)位于根项目目录中。此设置文件定义了项目级的存储库设置,并告知 Gradle 在构建应用时应包含哪些模块。多模块项目需要指定应进入最终构建的每个模块。

对于大多数项目,该文件默认如下所示

Kotlin

pluginManagement {

    /**
      * The pluginManagement.repositories block configures the
      * repositories Gradle uses to search or download the Gradle plugins and
      * their transitive dependencies. Gradle pre-configures support for remote
      * repositories such as JCenter, Maven Central, and Ivy. You can also use
      * local repositories or define your own remote repositories. Here we
      * define the Gradle Plugin Portal, Google's Maven repository,
      * and the Maven Central Repository as the repositories Gradle should use to look for its
      * dependencies.
      */

    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}
dependencyResolutionManagement {

    /**
      * The dependencyResolutionManagement.repositories
      * block is where you configure the repositories and dependencies used by
      * all modules in your project, such as libraries that you are using to
      * create your application. However, you should configure module-specific
      * dependencies in each module-level build.gradle file. For new projects,
      * Android Studio includes Google's Maven repository and the Maven Central
      * Repository by default, but it does not configure any dependencies (unless
      * you select a template that requires some).
      */

  repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  repositories {
      google()
      mavenCentral()
  }
}
rootProject.name = "My Application"
include(":app")

Groovy

pluginManagement {

    /**
      * The pluginManagement.repositories block configures the
      * repositories Gradle uses to search or download the Gradle plugins and
      * their transitive dependencies. Gradle pre-configures support for remote
      * repositories such as JCenter, Maven Central, and Ivy. You can also use
      * local repositories or define your own remote repositories. Here we
      * define the Gradle Plugin Portal, Google's Maven repository,
      * and the Maven Central Repository as the repositories Gradle should use to look for its
      * dependencies.
      */

    repositories {
        gradlePluginPortal()
        google()
        mavenCentral()
    }
}
dependencyResolutionManagement {

    /**
      * The dependencyResolutionManagement.repositories
      * block is where you configure the repositories and dependencies used by
      * all modules in your project, such as libraries that you are using to
      * create your application. However, you should configure module-specific
      * dependencies in each module-level build.gradle file. For new projects,
      * Android Studio includes Google's Maven repository and the Maven Central
      * Repository by default, but it does not configure any dependencies (unless
      * you select a template that requires some).
      */

    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "My Application"
include ':app'

顶层构建文件

顶层 build.gradle.kts 文件(针对 Kotlin DSL)或 build.gradle 文件(针对 Groovy DSL)位于根项目目录中。它通常定义项目中各模块所使用的插件的通用版本。

以下代码示例描述了创建新项目后,顶层构建脚本中的默认设置和 DSL 元素

Kotlin

plugins {

    /**
     * Use `apply false` in the top-level build.gradle file to add a Gradle
     * plugin as a build dependency but not apply it to the current (root)
     * project. Don't use `apply false` in sub-projects. For more information,
     * see Applying external plugins with same version to subprojects.
     */

    id("com.android.application") version "9.2.0" apply false
    id("com.android.library") version "9.2.0" apply false
    id("org.jetbrains.kotlin.android") version "2.3.21" apply false
}

Groovy

plugins {

    /**
     * Use `apply false` in the top-level build.gradle file to add a Gradle
     * plugin as a build dependency but not apply it to the current (root)
     * project. Don't use `apply false` in sub-projects. For more information,
     * see Applying external plugins with same version to subprojects.
     */

    id 'com.android.application' version '9.2.0' apply false
    id 'com.android.library' version '9.2.0' apply false
    id 'org.jetbrains.kotlin.android' version '2.3.21' apply false
}

模块级构建文件

模块级 build.gradle.kts(针对 Kotlin DSL)或 build.gradle 文件(针对 Groovy DSL)位于每个 project/module/ 目录中。它允许您为所在的特定模块配置构建设置。配置这些构建设置可以让您提供自定义打包选项(例如额外的构建类型和产品风味),并覆盖 main/ 应用清单或顶层构建脚本中的设置。

Android SDK 设置

应用程序的模块级构建文件包含一些设置,用于指示编译时使用的 Android SDK 版本、选择平台行为以及指定应用程序运行所需的最低版本。

Overview of SDK specifications in a Gradle build
图 1. 构建中的 Android SDK
compileSdk

compileSdk 决定了在编译源代码时可以使用哪些 Android 和 Java API。要使用最新的 Android 功能,请在编译时使用最新的 Android SDK。

某些 Android 平台 API 可能在较旧的 API 级别中不可用。您可以有条件地防护新功能的使用,或使用 AndroidX 兼容性库,以便在较低的 Android API 级别上使用新功能。

每个 Android SDK 都提供了一部分 Java API 供您在应用程序中使用。我可以并在 Java 或 Kotlin 源代码中使用哪些 Java API 表格显示了基于 Android SDK 版本可用的 Java API 级别。通过脱糖 (desugaring)(必须在构建中启用),较新的 Java API 可在早期版本的 Android 上得到支持。

如果您需要针对特定的次要 API 级别进行编译,请使用扩展的 compileSdk 块语法并指定 minorApiLevel

Kotlin

    android {
        compileSdk {
            version = release(36) {
                minorApiLevel = 1
            }
        }
    }
    

Groovy

    android {
        compileSdk {
            version = release(36) {
                minorApiLevel = 1
            }
        }
    }
    

如果您的 compileSdk 与当前 Android Studio 版本、AGP 或项目的库依赖项要求发生冲突,Android Studio 会显示警告。

minSdk

minSdk 指定了您希望应用支持的最低 Android 版本。设置 minSdk 会限制哪些设备可以安装您的应用。

支持较低版本的 Android 可能需要在代码中进行更多的条件检查,或更多地使用 AndroidX 兼容性库。您应该权衡支持较低版本的维护成本与仍在使用这些较低版本的用户百分比。有关当前版本使用百分比,请查看 Android Studio 新建项目向导中的版本图表。

当您在 Android Studio 中编辑代码或在构建过程中运行检查时,Lint 会针对您使用的在 minSdk 中不可用的 API 发出警告。您应该通过使较新功能具有条件性或使用 Appcompat 实现向后兼容性来解决这些问题。

targetSdk

targetSdk 有两个用途

  1. 它设置应用程序的运行时行为。
  2. 它证明您已针对该版本的 Android 进行了测试。

如果您在使用的 Android 版本高于 targetSdk 的设备上运行应用,Android 会以兼容模式运行您的应用,其行为类似于 targetSdk 中指示的较低版本。例如,当 API 23 引入运行时权限模型时,并非所有应用都准备好立即采用它。通过将 targetSdk 设置为 22,这些应用可以在 API 23 设备上运行而无需使用运行时权限,并且可以使用最新的 compileSdk 版本中包含的功能。Google Play 分发政策对目标 API 级别实施了额外政策

targetSdk 的值与 compileSdk 的值无关。例如,您可以拥有高于、等于或低于 compileSdktargetSdk 值。

注意:compileSdktargetSdk 的值不需要相同。请记住以下基本原则

  • compileSdk 让您能够使用新的 API
  • targetSdk 设置您应用的运行时行为

示例应用模块构建脚本

此示例 Android 应用模块构建脚本概述了一些基本的 DSL 元素和设置

Kotlin

/**
 * The first section in the build configuration applies the Android Gradle plugin
 * to this build and makes the android block available to specify
 * Android-specific build options.
 */

plugins {
    id("com.android.application")
}

/**
 * Locate (and possibly download) a JDK used to build your kotlin
 * source code. This also acts as a default for sourceCompatibility,
 * targetCompatibility and jvmTarget. Note that this does not affect which JDK
 * is used to run the Gradle build itself, and does not need to take into
 * account the JDK version required by Gradle plugins (such as the
 * Android Gradle Plugin)
 */
kotlin {
    jvmToolchain(11)
}

/**
 * The android block is where you configure all your Android-specific
 * build options.
 */

android {

    /**
     * The app's namespace. Used primarily to access app resources.
     */

    namespace = "com.example.myapp"

    /**
     * compileSdk specifies the Android API level Gradle should use to
     * compile your app. This means your app can use the API features included in
     * this API level and lower.
     */

    compileSdk = 36

    /**
     * The defaultConfig block encapsulates default settings and entries for all
     * build variants and can override some attributes in main/AndroidManifest.xml
     * dynamically from the build system. You can configure product flavors to override
     * these values for different versions of your app.
     */

    defaultConfig {

        // Uniquely identifies the package for publishing.
        applicationId = "com.example.myapp"

        // Defines the minimum API level required to run the app.
        minSdk = 23

        // Specifies the API level used to test the app.
        targetSdk = 36

        // Defines the version number of your app.
        versionCode = 1

        // Defines a user-friendly version name for your app.
        versionName = "1.0"
    }

    /**
     * The buildTypes block is where you can configure multiple build types.
     * By default, the build system defines two build types: debug and release. The
     * debug build type is not explicitly shown in the default build configuration,
     * but it includes debugging tools and is signed with the debug key. The release
     * build type applies ProGuard settings and is not signed by default.
     */

    buildTypes {

        /**
         * By default, Android Studio configures the release build type to enable code
         * shrinking, using minifyEnabled, and specifies the default ProGuard rules file.
         */

        getByName("release") {
            isMinifyEnabled = true // Enables code shrinking for the release build type.
            proguardFiles(
                getDefaultProguardFile("proguard-android.txt"),
                "proguard-rules.pro"
            )
        }
    }

    /**
     * The productFlavors block is where you can configure multiple product flavors.
     * This lets you create different versions of your app that can
     * override the defaultConfig block with their own settings. Product flavors
     * are optional, and the build system does not create them by default.
     *
     * This example creates a free and paid product flavor. Each product flavor
     * then specifies its own application ID, so that they can exist on the Google
     * Play Store or an Android device simultaneously.
     *
     * If you declare product flavors, you must also declare flavor dimensions
     * and assign each flavor to a flavor dimension.
     */

    flavorDimensions += "tier"
    productFlavors {
        create("free") {
            dimension = "tier"
            applicationId = "com.example.myapp.free"
        }

        create("paid") {
            dimension = "tier"
            applicationId = "com.example.myapp.paid"
        }
    }

    /**
     * To override source and target compatibility (if different from the
     * toolchain JDK version), add the following. All of these
     * default to the same value as kotlin.jvmToolchain. If you're using the
     * same version for these values and kotlin.jvmToolchain, you can
     * remove these blocks.
     */
    //compileOptions {
    //    sourceCompatibility = JavaVersion.VERSION_11
    //    targetCompatibility = JavaVersion.VERSION_11
    //}
    //kotlinOptions {
    //    jvmTarget = "11"
    //}
}

/**
 * The dependencies block in the module-level build configuration file
 * specifies dependencies required to build only the module itself.
 * To learn more, go to Add build dependencies.
 */

dependencies {
    implementation(project(":lib"))
    implementation("androidx.appcompat:appcompat:1.7.1")
    implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
}

Groovy

/**
 * The first line in the build configuration applies the Android Gradle plugin
 * to this build and makes the android block available to specify
 * Android-specific build options.
 */

plugins {
    id 'com.android.application'
}

/**
 * Locate (and possibly download) a JDK used to build your kotlin
 * source code. This also acts as a default for sourceCompatibility,
 * targetCompatibility and jvmTarget. Note that this does not affect which JDK
 * is used to run the Gradle build itself, and does not need to take into
 * account the JDK version required by Gradle plugins (such as the
 * Android Gradle Plugin)
 */
kotlin {
    jvmToolchain 11
}

/**
 * The android block is where you configure all your Android-specific
 * build options.
 */

android {

    /**
     * The app's namespace. Used primarily to access app resources.
     */

    namespace 'com.example.myapp'

    /**
     * compileSdk specifies the Android API level Gradle should use to
     * compile your app. This means your app can use the API features included in
     * this API level and lower.
     */

    compileSdk 36

    /**
     * The defaultConfig block encapsulates default settings and entries for all
     * build variants and can override some attributes in main/AndroidManifest.xml
     * dynamically from the build system. You can configure product flavors to override
     * these values for different versions of your app.
     */

    defaultConfig {

        // Uniquely identifies the package for publishing.
        applicationId 'com.example.myapp'

        // Defines the minimum API level required to run the app.
        minSdk 23

        // Specifies the API level used to test the app.
        targetSdk 36

        // Defines the version number of your app.
        versionCode 1

        // Defines a user-friendly version name for your app.
        versionName "1.0"
    }

    /**
     * The buildTypes block is where you can configure multiple build types.
     * By default, the build system defines two build types: debug and release. The
     * debug build type is not explicitly shown in the default build configuration,
     * but it includes debugging tools and is signed with the debug key. The release
     * build type applies ProGuard settings and is not signed by default.
     */

    buildTypes {

        /**
         * By default, Android Studio configures the release build type to enable code
         * shrinking, using minifyEnabled, and specifies the default ProGuard rules file.
         */

        release {
              minifyEnabled true // Enables code shrinking for the release build type.
              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    /**
     * The productFlavors block is where you can configure multiple product flavors.
     * This lets you create different versions of your app that can
     * override the defaultConfig block with their own settings. Product flavors
     * are optional, and the build system does not create them by default.
     *
     * This example creates a free and paid product flavor. Each product flavor
     * then specifies its own application ID, so that they can exist on the Google
     * Play Store or an Android device simultaneously.
     *
     * If you declare product flavors, you must also declare flavor dimensions
     * and assign each flavor to a flavor dimension.
     */

    flavorDimensions "tier"
    productFlavors {
        free {
            dimension "tier"
            applicationId 'com.example.myapp.free'
        }

        paid {
            dimension "tier"
            applicationId 'com.example.myapp.paid'
        }
    }

    /**
     * To override source and target compatibility (if different from the
     * tool chain JDK version), add the following. All of these
     * default to the same value as kotlin.jvmToolchain. If you're using the
     * same version for these values and kotlin.jvmToolchain, you can
     * remove these blocks.
     */
    //compileOptions {
    //    sourceCompatibility JavaVersion.VERSION_11
    //    targetCompatibility JavaVersion.VERSION_11
    //}
    //kotlinOptions {
    //    jvmTarget = '11'
    //}
}

/**
 * The dependencies block in the module-level build configuration file
 * specifies dependencies required to build only the module itself.
 * To learn more, go to Add build dependencies.
 */

dependencies {
    implementation project(":lib")
    implementation 'androidx.appcompat:appcompat:1.7.1'
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

Gradle 属性文件

Gradle 还包括两个属性文件,位于您的根项目目录中,您可以使用它们为 Gradle 构建工具本身指定设置

gradle.properties
在这里,您可以配置项目范围的 Gradle 设置,例如 Gradle 守护进程的最大堆大小。有关更多信息,请参阅构建环境
local.properties
为构建系统配置本地环境属性,包括以下内容
  • ndk.dir - NDK 的路径。此属性已被弃用。下载的所有 NDK 版本都安装在 Android SDK 目录下的 ndk 目录中。
  • sdk.dir - Android SDK 的路径。
  • cmake.dir - CMake 的路径。
  • ndk.symlinkdir - 在 Android Studio 3.5 及更高版本中,创建指向 NDK 的符号链接,该链接可以比安装的 NDK 路径更短。

将 NDK 重映射到更短的路径(仅限 Windows)

在 Windows 中,安装的 NDK 文件夹中的工具(例如 ld.exe)最终路径很长。这些工具对长路径的支持并不好。

要创建更短的路径,请在 local.properties 中设置属性 ndk.symlinkdir,以请求 Android Gradle 插件创建指向 NDK 的符号链接。该符号链接的路径可以比现有的 NDK 文件夹短。例如,ndk.symlinkdir = C:\ 会导致以下符号链接:C:\ndk\19.0.5232133

与 Gradle 文件同步项目

当您更改项目中的构建配置文件时,Android Studio 要求您同步项目文件,以便它可以导入您的构建配置更改并运行一些检查,以确保您的配置不会导致构建错误。

要同步您的项目文件,请点击您进行更改时出现的通知栏中的 Sync Now(如图 2 所示),或从菜单栏点击 Sync Project 。如果 Android Studio 在您的配置中发现任何错误(例如,您的源代码使用了仅在高于 compileSdkVersion 的 API 级别中才可用的 API 功能),Messages 窗口会描述该问题。

图 2. 在 Android Studio 中与构建配置文件同步项目。

源集

Android Studio 在逻辑上将每个模块的源代码和资源分组为源集 (source sets)。当您创建新模块时,Android Studio 会在模块内创建一个 main/ 源集。模块的 main/ 源集包含其所有构建变体使用的代码和资源。

额外的源集目录是可选的,当您配置新的构建变体时,Android Studio 不会自动为您创建它们。但是,创建类似于 main/ 的源集有助于组织 Gradle 仅在构建特定版本应用时应使用的文件和资源。

src/main/
此源集包含所有构建变体共有的代码和资源。
src/buildType/
创建此源集以包含仅用于特定构建类型的代码和资源。
src/productFlavor/
创建此源集以包含仅用于特定产品风味的代码和资源。

注意:如果您将构建配置为组合多个产品风味,您可以为风味维度之间产品风味的每个组合创建源集目录:src/productFlavor1ProductFlavor2/

src/productFlavorBuildType/
创建此源集以包含仅用于特定构建变体的代码和资源。

例如,要生成应用的 "fullDebug" 版本,构建系统会从以下源集中合并代码、设置和资源

  • src/fullDebug/ (构建变体源集)
  • src/debug/ (构建类型源集)
  • src/full/ (产品风味源集)
  • src/main/ (主要源集)

注意:在 Android Studio 中创建新文件或目录时,请使用 File > New 菜单选项为特定的源集创建它。您可以选择的源集基于您的构建配置,如果目录不存在,Android Studio 会自动创建所需的目录。

如果不同的源集包含同一文件的不同版本,Gradle 在决定使用哪个文件时会使用以下优先级顺序。左侧的源集会覆盖右侧源集的文件和设置

构建变体 > 构建类型 > 产品风味 > 主要源集 > 库依赖项

这允许 Gradle 使用特定于您尝试构建的构建变体的文件,同时重用应用其他版本共有的活动、应用程序逻辑和资源。

合并多个清单时,Gradle 使用相同的优先级顺序,因此每个构建变体可以在最终清单中定义不同的组件或权限。要了解有关创建自定义源集的更多信息,请阅读创建源集

版本目录 (Version catalogs)

如果您的构建包含多个具有共同依赖项的模块,或者您有多个具有共同依赖项的独立项目,我们建议您使用版本目录或物料清单 (BOM) 来指定通用版本。

其他构建系统

使用 Bazel 构建 Android 应用是可能的,但不受官方支持。Android Studio 不正式支持 Bazel 项目。

要更好地了解使用 Bazel 构建的当前局限性,请查看已知问题