Android AGP 7.0 适配,开始强制 JDK 11
本次跟随 Arctic Fox 更新的其中一个重点就是 AGP 7.0 的调整,估计很多直接升级到 AGP 7.0 的开发者都会发现项目出现一些异常,本篇主要结合官方简单介绍 AGP 7.0 下的主要调整内容。
跳过版本 5 和 6 直接进入 AGP 7.0.0 的原因,是为了和 Gradle 的版本 匹配,这意味着 AGP 7.x 就是和 Gradle 7.x API 一一对应。
通过此次版本号的更改,AGP 版本号将与 Android Studio 版本号分开,不过目前的情况看 Android Studio 和 Android Gradle 插件会同时发布。一般来说使用稳定版 AGP 的项目是应该可以在较新版本的 Android Studio 中打开。
运行 AGP 7 需要 JDK 11
是的,不要惊讶,使用 Android Gradle plugin 7.0 构建时需要 JDK 11 才能运行 Gradle。
但是也请不必过多当心,这里的 JDK 11 是免费的 OpenJDK 11 ,并且只要你更新到 Android Studio Arctic Fox ,它是直接捆绑了 JDK 11 并将 Gradle 配置为默认使用它,所以大多数情况下,如果你本地配置正常,是可以直接使用 AGP 7.0 的升级。
当然,你也可以手动选择配置,在 Project Structure
的 SDK Location
栏目,可以看到 JDK 的配置位置已经被移动到 Gradle Settings
。
在打开的 Gradle projects
可以看到 Gradle 对应的配置选项,并且有 Gradle JDK 等可选的参数,你可以选择自己的 Java SDK ,也可以选择 AS 自带的 JDK
比如 Mac 下可以看到捆绑的 JDK 位置在 /Applications/Android\ Studio.app/Contents/jre/Contents/Home/bin/java
如果是需要抛开 Android Studio 来配置运行的 AGP 时,通过会使用 JAVA_HOME 环境变量 或
-Dorg.gradle.java.home
命令行选项 设置为 JDK 11 的安装目录来升级 JDK 版本。
Variant API stable
新的 Variant API 现在已经是稳定的版本, 可以查看 com.android.build.api.variant 包中的新接口,以及 gradle-recipes GitHub 项目中的示例。
作为新 Variant API 的一部分,通过 Artifacts 接口提供了许多称为 artifacts 的中间文件,如合并的清单功能,可以通过使用第三方插件和代码安全地获取和定制。
后续将通过添加新功能和增加可用于定制的中间件的数量来继续扩展 Variant API。
Lint 的行为变化
改进了库依赖项的 lint
运行 lint with checkDependencies = true
现在比以前更快了,对于库依赖的 Android App 的项目,建议使用 checkDependencies
= true
的方式,和运行 ./gradlew :app:lint
,这将并行分析的所有依赖模块,并且提供一份单独包含有 App 和依赖的 issues 文件。
// build.gradle
android {
...
lintOptions {
checkDependencies true
}
}
// build.gradle.kts
android {
...
lint {
isCheckDependencies = true
}
}
Lint 任务现在可以 UP-TO-DATE
如果模块的源和资源没有改变,则不需要再次运行该模块的 lint 分析任务,当出现这种情况时,任务的执行在 Gradle 输出中显示为“UP-TO-DATE”。
通过此次的变换,当在带有 checkDependencies = true
的应用程序模块上运行 lint 时,只有发生更改的模块需要运行分析,因此 Lint 可以运行得更快。
如果输入没有发生更改,则 Lint 报告任务也不需要运行,这里有一个相关的已知问题是,当 lint 任务为 UP-TO-DATE 时,没有打印到 stdout 的 lint 文本输出(问题 #191897708)。
在动态功能模块上运行 lint
AGP 不再支持从动态功能模块运行 lint,从相应的模块运行 lint 将在其动态功能模块上运行 lint,并将所有问题包含在应用程序的 lint 报告中。
一个相关的已知问题 是,当 checkDependencies = true
时,从模块运行 lint 不再会检查动态功能库依赖项,除非它们也是应用程序的依赖项(问题 #191977888)。
仅在默认 variant 上运行 lint
运行 ./gradlew :app:lint
现在只运行默认的 variant , 在以前版本的 AGP 中,它将为所有 variants 运行 lint。
Missing class warnings in R8 shrinker
R8 可以更精确和更一致地处理丢失类和 -dontwarn
的选项,因此开发者应该开始针对 R8 发出的缺失类警告进行处理。
当 R8 遇到未在 App 或其依赖项之一中定义的类引用时,它将发出警告,并显示在您的构建输出中。例如:
R8: Missing class: java.lang.instrument.ClassFileTransformer
此警告意味着 java.lang.instrument.ClassFileTransformer
在分析代码时找不到类定义,虽然这些经过可能存在错误,所以开发者可能希望可以忽略此警告,忽略警告的两个常见原因是:
-
- 以 JVM 为目标的库和缺少的类是 JVM 库类型(如上例所示)。
-
- 依赖项之一使用仅限编译时的 API。
所以可以通过向文件添加 -dontwarn
规则来向 proguard-rules.pro
忽略缺少的类警告,例如:
-dontwarn java.lang.instrument.ClassFileTransformer
为方便起见,AGP 将生成一个包含所有可能丢失的规则的文件,将它们写入如下文件路径 app/build/outputs/mapping/release/missing_rules.txt
, 这样可以方便地将规则添加到 proguard-rules.pro
文件以忽略警告。
在 AGP 7.0 中缺少类消息将显示为警告,当然你可以通过
android.r8.failOnMissingClasses = true
在gradle.properties
讲他们变成 errors 。
在 AGP 8.0 中,这些警告将变为破坏构建的 errors,你可以通过将选项添加 -ignorewarnings
配置到 proguard-rules.pro
文件来保持 AGP 7.0 行为,但不建议这样做。
移除了 Android Gradle 插件构建缓存
AGP 构建缓存已在 AGP 4.1 中删除,之前在 AGP 2.3 中引入是为了补充 Gradle 构建缓存,AGP 构建缓存被 AGP 4.1 中的 Gradle 构建缓存完全取代,这个变换其实不会影响构建时间。
在 AGP 7.0 中 android.enableBuildCache
属性、android.buildCacheDir
属性和cleanBuildCache
任务已经被删除。
在项目中使用 Java 11
现在可以项目中使用 Java 11 去编译你的项目代码了,开发者能够使用更新后的语言功能,例如私有接口方法、匿名类的 diamond 运输符和 lambda 参数的局部变量语法。
要启用此功能,请设置 compileOptions
为所需的 Java 版本并设置 compileSdkVersion
为 30 或更高版本:
// build.gradle
android {
compileSdkVersion 30
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
// For Kotlin projects
kotlinOptions {
jvmTarget = "11"
}
}
// build.gradle.kts
android {
compileSdkVersion(30)
compileOptions {
sourceCompatibility(JavaVersion.VERSION_11)
targetCompatibility(JavaVersion.VERSION_11)
}
kotlinOptions {
jvmTarget = "11"
}
}
已知的问题
与 1.?4.?x 的 Kotlin 多平台插件兼容
Android Gradle 插件 7.0.0 与 Kotlin 多平台插件 1.5.0 及更高版本兼容。
使用 Kotlin 多平台支持的项目需要更新到 Kotlin 1.5.0 才能使用 Android Gradle 插件 7.0.0。
缺少 lint 输出
当 lint 任务是最新的(问题 #191897708)时,文本输出没有打印到 stdout 的 lint ,此问题将在 Android Gradle 插件 7.1 中修复。
并非所有动态功能库依赖项都经过 lint 检查
checkDependencies = true
从应用程序模块运行 lint 时,不会检查动态功能库依赖项,除非它们也是应用程序依赖项(问题 #191977888)。