Android Gradle 插件 4.0.0(2020 年 4 月)

此版本的 Android 插件需要以下内容

4.0.1(2020 年 7 月)

此次次要更新支持与 Android 11 的新默认设置和功能兼容,例如 Android 11 中的包可见性

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

Android Gradle 插件 4.1+ 已与新的 <queries> 声明兼容;但是,旧版本不兼容。如果您添加了 <queries> 元素,或者如果您开始依赖支持面向 Android 11 的库或 SDK,则在构建应用时可能会遇到清单合并错误。

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

最低版本 默认版本 备注
Gradle 6.1.1 6.1.1 要了解更多信息,请参阅 更新 Gradle
SDK 构建工具 29.0.2 29.0.2 安装配置 SDK 构建工具。

有关此新功能的更多信息,请参阅 Android 11 中的包可见性

新功能

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

支持 Android Studio 构建分析器

构建分析器窗口可帮助您了解和诊断构建过程中的问题,例如禁用的优化和配置不正确的任务。当您在 Android Studio 4.0 及更高版本中使用 Android Gradle 插件 4.0.0 及更高版本时,此功能可用。您可以从 Android Studio 中打开构建分析器窗口,方法如下

  1. 如果尚未执行此操作,请通过从菜单栏中选择构建 > 生成项目来构建您的应用。
  2. 从菜单栏中选择查看 > 工具窗口 > 构建
  3. 构建窗口中,以下列方式之一打开构建分析器窗口
    • 在 Android Studio 完成构建项目后,点击构建分析器选项卡。
    • 在 Android Studio 完成构建项目后,点击构建输出窗口右侧的链接。

**构建分析器**窗口在左侧以树状结构组织可能的构建问题。您可以检查并点击每个问题以在右侧的面板中调查其详细信息。当 Android Studio 分析您的构建时,它会计算确定构建持续时间的任务集,并提供可视化效果来帮助您了解每个任务的影响。您还可以通过展开**警告**节点来获取有关警告的详细信息。

要了解更多信息,请阅读识别构建速度下降

D8 和 R8 中的 Java 8 库去糖化

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

通过称为去糖化的过程,Android Studio 3.0 及更高版本中的 DEX 编译器 D8 已经为 Java 8 语言特性(例如 lambda 表达式、默认接口方法、使用资源尝试等等)提供了大量支持。在 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 的错误修复)

为了支持这些语言 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 文件中包含上述代码段

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

  • 您希望单独对库模块运行 lint。这是为了帮助 lint 识别语言 API 的有效用法并避免报告错误警告。

启用或禁用构建功能的新选项

Android Gradle 插件 4.0.0 引入了一种新的方法来控制要启用和禁用的构建功能,例如 View Binding 和 Data Binding。添加新功能时,默认情况下会禁用它们。然后,您可以使用 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 功能,后者依赖于基本模块,如下图所示。

Feature on feature dependencies

功能模块 :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 中启用功能间依赖关系功能(例如,在编辑运行配置时支持该功能),方法是单击菜单栏中的**帮助 > 编辑自定义 VM 选项**,并包含以下内容

-Drundebug.feature.on.feature=true

依赖项元数据

当使用 Android Gradle 插件 4.0.0 及更高版本构建您的应用时,插件会包含描述编译到您的应用中的依赖项的元数据。上传您的应用时,Play Console 会检查此元数据,从而为您提供以下好处

  • 获取有关应用使用的 SDK 和依赖项的已知问题的警报
  • 接收可操作的反馈以解决这些问题

数据会被压缩,并使用 Google Play 签名密钥进行加密,并存储在发布应用的签名块中。但是,您可以在以下目录中的本地中间构建文件中自行检查元数据:<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 仅使这些库可用于您的构建;您仍然必须配置构建脚本才能使用它们。

库使用 Prefab 包格式导出。

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

通常,包名称与 Maven 工件名称匹配,模块名称与库名称匹配,但并非总是如此。因为您需要知道库的包名称和模块名称,所以您可能需要查阅依赖项的文档以确定这些名称是什么。

配置您的外部原生构建系统

要查看需要遵循的步骤,请按照您计划使用的外部原生构建系统的以下步骤操作。

包含原生代码的每个应用的 AAR 依赖项都会公开一个 Android.mk 文件,您需要将其导入到您的 ndk-build 项目中。您可以使用 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 构建公开一个 配置文件包{: .external},您可以使用 find_package{: .external} 命令导入它。此命令搜索与给定包名称和版本匹配的配置文件包,并公开其定义的目标以在您的构建中使用。例如,如果您的应用程序定义了 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.so 链接到 libcurl.so 并将 libcurl.so 打包到 APK 或应用包中。有关其他信息,请参阅 curl prefab 示例{:.external}。

行为更改

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

v1/v2 签名配置更新

signingConfig 块中应用签名配置的行为已更改为以下内容

v1 签名

  • 如果显式启用 v1SigningEnabled,则 AGP 会执行 v1 应用签名。
  • 如果用户显式禁用 v1SigningEnabled,则不会执行 v1 应用签名。
  • 如果用户未显式启用 v1 签名,则可以根据 minSdktargetSdk 自动禁用它。

v2 签名

  • 如果显式启用 v2SigningEnabled,则 AGP 会执行 v2 应用签名。
  • 如果用户显式禁用 v2SigningEnabled,则不会执行 v2 应用签名。
  • 如果用户未显式启用 v2 签名,则可以根据 targetSdk 自动禁用它。

这些更改允许 AGP 通过根据用户是否显式启用这些标志来禁用签名机制来优化构建。在此版本之前,即使显式启用了 v1Signing,也可能将其禁用,这可能会造成混淆。

已移除 featureinstantapp Android Gradle 插件

Android Gradle 插件 3.6.0 已弃用 Feature 插件 (com.android.feature) 和 Instant App 插件 (com.android.instantapp),建议使用 Dynamic Feature 插件 (com.android.dynamic-feature) 来构建和打包使用 Android 应用包 的即时应用。

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

注意:要在 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 外部原生构建使用的任何预构建库。您可能在模块的 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'

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

已知问题

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

Gradle 工作机制中的竞争条件

Android Gradle 插件 4.0 中的更改在使用 &endash;&endash;no&endash;daemon 和 Gradle 6.3 或更低版本时可能会触发 Gradle 中的竞争条件,导致构建在构建完成后挂起。

此问题将在 Gradle 6.4 中修复。