Android Gradle 插件 4.0.0(2020 年 4 月)

此版本的 Android 插件需要使用以下工具:

4.0.1(2020 年 7 月)

本次要更新支持Android 11 中软件包可见性的新默认设置和功能兼容。

在以前的 Android 版本中,应用可以查看设备上安装的所有应用的列表。从 Android 11(API 级别 30)开始,默认情况下,应用只能访问经过过滤的已安装软件包列表。如需让应用查看系统上更广泛的应用列表,您现在需要在应用或库的 Android 清单中添加 <queries> 元素

Android Gradle 插件 4.1 及更高版本已与新的 <queries> 声明兼容;不过,较低的版本不兼容。如果您添加 <queries> 元素或者开始依赖于支持以 Android 11 为目标平台的库或 SDK,在构建应用时可能会遇到清单合并错误。

为了解决此问题,我们将针对 AGP 3.3 及更高版本发布一组补丁。如果您使用的是旧版 AGP,请升级到以下某个版本:

如果您使用的是
AGP 版本...
...请升级到
4.0.* 4.0.1
3.6.* 3.6.4
3.5.* 3.5.4
3.4.* 3.4.3
3.3.* 3.3.3

如需详细了解这项新功能,请参阅 Android 11 中的软件包可见性

新功能

此版本的 Android Gradle 插件包含以下新功能。

对 Android Studio Build Analyzer 的支持

Build Analyzer 窗口可帮助您了解和诊断与构建流程有关的问题,如优化被停用和任务配置不当问题。当您将 Android Studio 4.0 及更高版本与 Android Gradle 插件 4.0.0 及更高版本一起使用时,此功能可用。您可以从 Android Studio 中打开 Build Analyzer 窗口,具体操作步骤如下:

  1. 通过从菜单栏中依次选择 Build > Make Project 来构建应用(如果您尚未这样做)。
  2. 从菜单栏中依次选择 View > Tool Windows > Build
  3. Build 窗口中,通过以下某种方式打开 Build Analyzer 窗口:
    • Android Studio 构建完您的项目后,点击 Build Analyzer 标签页。
    • Android Studio 构建完您的项目后,点击 Build Output 窗口右侧的链接。

Build Analyzer 窗口将可能存在的构建问题整理成左侧的树状图。您可以检查并点击每个问题,以在右侧的面板中调查其详细信息。当 Android Studio 分析您的 build 时,它会计算决定构建时长的一组任务,并提供直观的图表来帮助您了解其中每项任务所产生的影响。您也可以展开 Warnings 节点,以获取有关警告的详细信息。

如需了解详情,请参阅发现构建速度减慢的问题

D8 和 R8 中的 Java 8 库脱糖

Android Gradle 插件现在支持使用多种 Java 8 语言 API,而无需为应用设置最低 API 级别。

通过一个称为“脱糖”的过程,Android Studio 3.0 及更高版本中的 DEX 编译器 D8 已经为 Java 8 语言功能(如 lambda 表达式、默认接口方法、try-with-resources 等等)提供了大量的支持。在 Android Studio 4.0 中,脱糖引擎经过扩展,能够使 Java 语言 API 脱糖。这意味着,您现在可以在支持旧版 Android 的应用中添加过去仅在最新 Android 版本中可用的标准语言 API(如 java.util.streams)。

此版本支持下面一组 API:

  • 顺序流 (java.util.stream)
  • java.time 的子集
  • java.util.function
  • java.util.{Map,Collection,Comparator} 的最近新增内容
  • 可选内容(java.util.Optionaljava.util.OptionalIntjava.util.OptionalDouble)以及对上述 API 很有用的一些其他新类
  • java.util.concurrent.atomic 的一些新增内容(AtomicIntegerAtomicLongAtomicReference 的新方法)
  • ConcurrentHashMap(包含 Android 5.0 的 bug 修复)

为了支持这些语言 API,D8 编译了一个单独的 DEX 文件(其中包含缺失 API 的实现),并将其添加到您的应用中。脱糖过程会重新编写应用的代码,以便在运行时改用此库。

如需启用对这些语言 API 的支持,请在应用模块build.gradle 文件中添加以下代码:

android {
  defaultConfig {
    // Required when setting minSdkVersion to 20 or lower
    multiDexEnabled true
  }

compileOptions { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true // Sets Java compatibility to Java 8 sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }

dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.4' }

android {
  defaultConfig {
    // Required when setting minSdkVersion to 20 or lower
    multiDexEnabled = true
  }

compileOptions { // Flag to enable support for the new language APIs isCoreLibraryDesugaringEnabled = true // Sets Java compatibility to Java 8 sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } }

dependencies { coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.0.4") }

请注意,在以下情况下,您可能还需要在相应库模块build.gradle 文件中添加以上代码段:

  • 库模块的插桩测试会使用这些语言 API(直接使用,或者通过库模块或其依赖项使用)。这是为了向您的插桩测试 APK 提供缺失的 API。

  • 您想单独在该库模块上运行 lint。这是为了帮助 lint 识别这些语言 API 的有效使用情况,并避免报告虚假警告。

用于启用或停用构建功能的新选项

Android Gradle 插件 4.0.0 引入了一种新方法来控制您要启用和停用哪些构建功能,如视图绑定和数据绑定。添加新功能后,默认情况下,这些功能处于停用状态。您随后可以使用 buildFeatures 代码块来仅启用所需的功能,它可以帮助您优化项目的构建性能。您可以在模块级 build.gradle 文件中为每个模块设置相应的选项,如下所示:

android {
  // The default value for each feature is shown below. You can change the value to
  // override the default behavior.
  buildFeatures {
    // Determines whether to generate a BuildConfig class.
    buildConfig = true
    // Determines whether to support View Binding.
    // Note that the viewBinding.enabled property is now deprecated.
    viewBinding = false
    // Determines whether to support Data Binding.
    // Note that the dataBinding.enabled property is now deprecated.
    dataBinding = false
    // Determines whether to generate binder classes for your AIDL files.
    aidl = true
    // Determines whether to support RenderScript.
    renderScript = true
    // Determines whether to support injecting custom variables into the module’s R class.
    resValues = true
    // Determines whether to support shader AOT compilation.
    shaders = true
  }
}
android {
  // The default value for each feature is shown below. You can change the value to
  // override the default behavior.
  buildFeatures {
    // Determines whether to generate a BuildConfig class.
    buildConfig = true
    // Determines whether to support View Binding.
    // Note that the viewBinding.enabled property is now deprecated.
    viewBinding = false
    // Determines whether to support Data Binding.
    // Note that the dataBinding.enabled property is now deprecated.
    dataBinding = false
    // Determines whether to generate binder classes for your AIDL files.
    aidl = true
    // Determines whether to support RenderScript.
    renderScript = true
    // Determines whether to support injecting custom variables into the module’s R class.
    resValues = true
    // Determines whether to support shader AOT compilation.
    shaders = true
  }
}

您还可以为项目中的所有模块指定这些功能的默认设置,方法是在项目的 gradle.properties 文件中添加下面的一项或多项,如下所示。请注意,您仍然可以使用模块级 build.gradle 文件中的 buildFeatures 代码块替换这些项目范围的默认设置。

android.defaults.buildfeatures.buildconfig=true
android.defaults.buildfeatures.aidl=true
android.defaults.buildfeatures.renderscript=true
android.defaults.buildfeatures.resvalues=true
android.defaults.buildfeatures.shaders=true

功能对功能的依赖性

在以前的 Android Gradle 插件版本中,所有功能模块都只能依赖于应用的基本模块。使用 Android Gradle 插件 4.0.0 时,您现在可以添加依赖于其他功能模块的功能模块。也就是说,:video 功能可以依赖于 :camera 功能,而后者依赖于基本模块,如下图所示。

功能对功能的依赖性

:video 功能模块依赖于 :camera 功能,而后者依赖于 :app 基本模块。

这意味着,当您的应用请求下载某个功能模块时,它也会下载该模块所依赖的其他功能模块。为您的应用创建功能模块后,您可以在模块的 build.gradle 文件中声明功能对功能的依赖性。例如,:video 模块声明对 :camera 的依赖性,如下所示:

// In the build.gradle file of the ':video' module.
dependencies {
  // All feature modules must declare a dependency
  // on the base module.
  implementation project(':app')
  // Declares that this module also depends on the 'camera'
  // feature module.
  implementation project(':camera')
  ...
}
// In the build.gradle file of the ':video' module.
dependencies {
    // All feature modules must declare a dependency
    // on the base module.
    implementation(project(":app"))
    // Declares that this module also depends on the 'camera'
    // feature module.
    implementation(project(":camera"))
    ...
}

此外,您还应在 Android Studio 中启用功能对功能的依赖性功能(例如,为了在修改运行配置时支持该功能),方法是从菜单栏中依次点击 Help > Edit Custom VM Options,并添加以下代码:

-Drundebug.feature.on.feature=true

依赖项元数据

使用 Android Gradle 插件 4.0.0 及更高版本构建应用时,该插件包含描述已编译到应用中的依赖项的元数据。上传应用时,Play 管理中心会检查此元数据,以便为您提供以下优势:

  • 获取有关您的应用使用的 SDK 和依赖项的已知问题的提醒
  • 接收切实可行的反馈来解决这些问题

数据经过压缩,并由 Google Play 签名密钥加密,然后存储在您的发布应用的签名分块中。但是,您可以在以下目录中的本地中间 build 文件中自行检查元数据:<project>/<module>/build/outputs/sdk-dependencies/release/sdkDependency.txt

如果您不希望分享这些信息,可以通过在模块的 build.gradle 文件中添加以下代码来选择退出:

android {
  dependenciesInfo {
      // Disables dependency metadata when building APKs.
      includeInApk = false
      // Disables dependency metadata when building Android App Bundles.
      includeInBundle = false
  }
}
android {
  dependenciesInfo {
      // Disables dependency metadata when building APKs.
      includeInApk = false
      // Disables dependency metadata when building Android App Bundles.
      includeInBundle = false
  }
}

从 AAR 依赖项导入原生库

您现在可以从应用的 AAR 依赖项导入 C/C++ 库。当您按照下述配置步骤操作时,Gradle 会自动使这些原生库可供您的外部原生构建系统(如 CMake)使用。请注意,Gradle 仅向您的 build 提供这些库;您仍然必须配置构建脚本才能使用它们。

系统会以 Prefab 软件包格式将库导出。

每个依赖项最多可公开一个包含一个或多个模块的 Prefab 软件包。Prefab 模块是一个库,它可以是共享库或静态库,也可以是仅包含头文件的库。

通常,软件包名称与 Maven 工件名称匹配,模块名称与库名称匹配,但并不总是如此。由于您需要知道库的软件包和模块名称,因此您可能需要参考依赖项文档以确定这些名称。

配置外部原生构建系统

如需查看您需要遵循的步骤,请针对您计划使用的外部原生构建系统执行以下步骤。

应用的每个包含原生代码的 AAR 依赖项都会公开您需要导入 ndk-build 项目的 Android.mk 文件。您可以使用 import&endash;module 命令导入此文件,该命令会搜索您在 ndk-build 项目中使用 import&endash;add&endash;path 属性指定的路径。例如,如果您的应用定义了 libapp.so 并且使用了 curl,您应在 Android.mk 文件中添加以下代码:

  1. 对于 CMake:

    add_library(app SHARED app.cpp)

    # Add these two lines. find_package(curl REQUIRED CONFIG) target_link_libraries(app curl::curl)

  2. 对于 ndk-build

    include $(CLEAR_VARS)
    LOCAL_MODULE := libapp
    LOCAL_SRC_FILES := app.cpp
    # Link libcurl from the curl AAR.
    LOCAL_SHARED_LIBRARIES := curl
    include $(BUILD_SHARED_LIBRARY)

    # If you don't expect that your project will be built using versions of the NDK # older than r21, you can omit this block. ifneq ($(call ndk-major-at-least,21),true) $(call import-add-path,$(NDK_GRADLE_INJECTED_IMPORT_PATH)) endif

    # Import all modules that are included in the curl AAR. $(call import-module,prefab/curl)

AAR 中包含的原生依赖项通过 CMAKE_FIND_ROOT_PATH{: .external} 变量向您的 CMake 项目公开。当系统调用 CMake 时,Gradle 会自动设置此值,因此如果您的构建系统修改了此变量,请务必对其附加相应值而不是直接赋值。

每个依赖项都会向您的 CMake build 公开 config-file 软件包{: .external},您可以使用 find_package{: .external} 命令将其导入。此命令会搜索与给定软件包名称和版本匹配的 config-file 软件包,并公开它定义的要在您的 build 中使用的目标。例如,如果您的应用定义了 libapp.so 并且使用了 curl,您应在 CMakeLists.txt 文件中添加以下代码:


add_library(app SHARED app.cpp)

# Add these two lines. find_package(curl REQUIRED CONFIG) target_link_libraries(app curl::curl)

您现在可以在 app.cpp 中指定 #include "curl/curl.h"。当您构建项目时,您的外部原生构建系统会自动关联 libapp.solibcurl.so 并将 libcurl.so 打包在 APK 或 app bundle 中。如需了解详情,请参阅 curl prefab 示例{:.external}。

行为变更

使用此版本的插件时,您可能会遇到以下行为方面的变更。

v1/v2 签名配置更新

signingConfig 块中应用签名配置的行为变更如下:

v1 签名

  • 如果 v1SigningEnabled 已显式启用,AGP 会执行 v1 应用签名。
  • 如果用户显式停用了 v1SigningEnabled,v1 应用签名便不会执行。
  • 如果用户未显式启用 v1 签名,系统可能会根据 minSdktargetSdk 自动停用 v1 签名。

v2 签名

  • 如果 v2SigningEnabled 已显式启用,AGP 会执行 v2 应用签名。
  • 如果用户显式停用了 v2SigningEnabled,v2 应用签名便不会执行。
  • 如果用户未显式启用 v2 签名,系统可能会根据 targetSdk 自动停用 v2 签名。

这些变更可让 AGP 根据用户是否已显式启用这些标志来停用相应签名机制,从而优化 build。在此版本之前,即使 v1Signing 已获显式启用,也可能会被停用,这会使用户感到迷惑。

移除了 featureinstantapp Android Gradle 插件

Android Gradle 插件 3.6.0 废弃了功能插件 (com.android.feature) 和免安装应用插件 (com.android.instantapp),改为使用动态功能插件 (com.android.dynamic-feature),以通过 Android App Bundle 构建和打包免安装应用。

在 Android Gradle 插件 4.0.0 及更高版本中,完全移除了这些已废弃的插件。因此,如需使用最新的 Android Gradle 插件,您需要迁移免安装应用以支持 Android App Bundle。通过迁移免安装应用,您可以利用 App Bundle 的优势,并简化应用的模块化设计

注意:如需打开使用 Android Studio 4.0 及更高版本中已移除的插件的项目,项目必须使用 Android Gradle 插件 3.6.0 或更低版本。

移除了“分离注解处理”功能

移除了将注解处理分离到一项专门任务中的功能。此选项过去用于在纯 Java 项目中使用非增量注解处理器时维持增量 Java 编译;过去的启用方法是在 gradle.properties 文件中将 android.enableSeparateAnnotationProcessing 设为 true,但这种方法不再起作用。

您应改为使用增量注解处理器来提升构建性能。

废弃了 includeCompileClasspath

Android Gradle 插件不再检查或添加您在编译类路径上声明的注解处理器,并且 annotationProcessorOptions.includeCompileClasspath DSL 属性不再有任何作用。如果您在编译类路径上添加注解处理器,可能会遇到以下错误:

Error: Annotation processors must be explicitly declared now.

如需解决此问题,您必须在 build.gradle 文件中使用 annotationProcessor 依赖项配置添加注解处理器。如需了解详情,请参阅添加注解处理器

自动打包 CMake 使用的预构建依赖项

早期版本的 Android Gradle 插件要求您使用 jniLibs 明确打包您的 CMake 外部原生 build 使用的所有预构建库。您的库可能位于模块的 src/main/jniLibs 目录中,也可能位于在 build.gradle 文件中配置的某个其他目录中:

sourceSets {
  main {
    // The libs directory contains prebuilt libraries that are used by the
    // app's library defined in CMakeLists.txt via an IMPORTED target.
    jniLibs.srcDirs = ['libs']
  }
}
sourceSets {
  main {
    // The libs directory contains prebuilt libraries that are used by the
    // app's library defined in CMakeLists.txt via an IMPORTED target.
    jniLibs.setSrcDirs(listOf("libs"))
  }
}

有了 Android Gradle 插件 4.0,上述配置不再是必需的,并且会导致构建失败:

* What went wrong:
Execution failed for task ':app:mergeDebugNativeLibs'.
  > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
    > More than one file was found with OS independent path 'lib/x86/libprebuilt.so'

外部原生 build 现在会自动打包这些库,因此使用 jniLibs 明确打包库会导致重复。为了避免构建错误,请将预构建库移至 jniLibs 之外的位置,或从 build.gradle 文件中移除 jniLibs 配置。

已知问题

本部分介绍 Android Gradle 插件 4.0.0 中存在的已知问题。

Gradle 工作器机制中的竞态条件

Android Gradle 插件 4.0 中的变更会在采用 &endash;&endash;no&endash;daemon 配置运行的 Gradle 和 Gradle 6.3 或更低版本中触发一种竞态条件,导致 build 在完成后挂起。

此问题将在 Gradle 6.4 中修复。