升级依赖项后,您可以访问其最新功能、错误修复和改进。要升级依赖项,您需要了解 Gradle 如何解析您请求的版本、相关的风险以及您可以采取的减轻这些风险的步骤。
考虑您的升级策略
任何升级中最重要的步骤是风险分析。确定您对要升级的每个依赖项的舒适程度。定义升级策略时,需要考虑很多因素,包括
构建库 |
您是在构建用户下载并在设备上运行的应用程序?还是在构建库以帮助其他开发者构建其应用程序? 如果您正在构建应用程序,则应专注于保持应用程序的最新和稳定性。 如果您正在构建库,则应关注其他开发者的应用程序。您的升级会影响您的使用者。如果您升级了其中一个依赖项,则该版本将成为 Gradle 依赖项解析的候选对象,可能会破坏应用程序对该依赖项的使用。 首先 - 尽可能减少库的依赖项。依赖项越少,对使用者 依赖项解析 的影响就越小。 务必遵循 语义版本控制 以帮助指示您正在进行的更改类型。例如,AndroidX 遵循语义版本控制并添加了 预发布版本方案。尽量避免 考虑为用户创建库的候选发布版本 (RC) 以进行早期测试。 有关保持库的应用程序二进制接口 (ABI) 兼容性的详细信息,请参阅 库作者的向后兼容性指南。使用集成测试和 二进制兼容性验证器 等工具来确保您的 ABI 更改与您预期的版本更改相符。 如果您在库的较低版本中发布了 如果您的库升级需要进行重大更改,可能会给您的使用者带来很大的困扰,请考虑将其作为新的构件发布,以便旧版本和新版本可以共存,并允许更渐进的推广。 注意:如果您的某个依赖项的升级包含重大的 API 更改,您可能需要在 |
发布周期 |
您多久发布一次您的应用程序或库? 较短的开发和发布周期
较长的开发和发布周期
|
跟上最新功能 |
您是喜欢使用最新的可用功能和API,还是只在需要功能或错误修复时才进行升级? 考虑频繁升级的权衡。未来的升级更容易(需要集成的更改更少),但您更频繁地承担升级风险。 测试库的预发布(alpha、beta、候选发布)版本的升级可以帮助在稳定版本可用时做好准备。 |
新的依赖项 |
如果您要添加新的依赖项,请考虑一个严格的审查流程,该流程会检查该库的所有风险标准,以确保已对其进行了正确的评估。不允许在未经审查的情况下添加新的依赖项。 |
专用团队 |
您有专门的构建团队吗?您的软件工程师维护构建吗?专门的团队通常可以花更多时间分析升级风险并测试新版本,以确保构建在工程师使用新版本之前正常工作。 |
升级类型 |
有些升级比其他升级更重要。考虑一下哪些对您最重要。 构建工具升级(例如 Gradle 和 Gradle 插件)通常对您的用户的影响较小,并且大部分风险都在您的构建内部。构建本身有助于验证这些更改。库和 SDK 升级更难以验证,它们对您的用户构成更高的风险。 Android Gradle 插件 (AGP) — 用于构建您的 Android 应用程序或库的工具。这是您可以进行的最关键的升级,因为它通常包含或启用性能改进、错误修复、新的 lint 规则以及对新 Android 平台版本的支持。 Gradle — 当您升级 AGP 或其他 Gradle 插件时,您通常需要升级 Gradle。 其他 Gradle 插件 — 有时 Gradle 的插件 API 会发生更改。当您升级 Gradle 时,请检查您使用的插件的升级。 Kotlin 和 Java — 一些库和插件需要 Kotlin 或 Java 的最低版本,或者您想利用新的语言特性、API 或性能改进。 Android 平台 — Play 商店要求定期升级 Android SDK。您应尽快测试新版本的 Android SDK。一些 SDK 升级需要更改您的应用程序,例如新的权限或使用新的 API。 库 — 您是否想根据库与您整体架构的接近程度来确定其优先级?
Android Studio — 使 Android Studio 保持最新状态可以让您访问底层 IntelliJ IDEA 平台中的最新功能和错误修复,以及用于处理最新 Android SDK 的工具。 |
可用的工具 |
有很多工具和插件可以帮助您进行升级。像Dependabot和Renovate这样的工具会自动升级构建中的库版本,但请务必分析结果以检查风险。 |
特定类型升级的策略
升级某些类型的依赖项可能会产生级联效应,需要升级其他类型的依赖项。我们在工具和库的相互依赖性中讨论了构建元素之间的关系。
升级每种类型的组件时,请考虑升级如何影响构建中的其他组件。
Android Gradle 插件 (AGP) |
Android Studio 包含一个AGP 升级助手,可以帮助完成这些任务。 如果您使用助手或手动执行升级,请考虑以下事项 查看AGP 发行说明。 将Gradle升级到至少列出的版本。 将Android Studio升级到支持所选 AGP 版本的版本。 使用支持您要使用的Android SDK的 Android Studio 和 AGP 版本。 检查与 SDK 构建工具、NDK 和 JDK 的兼容性。 如果您开发了一个扩展或使用 AGP 数据的 Gradle 插件(用于内部或公共用途),请检查您是否需要升级您的插件。有时 AGP 会弃用并在以后删除 API,从而导致与以前的插件不兼容。 |
Kotlin 编译器、语言和运行时 |
查看Kotlin 发行说明以了解已知问题和不兼容性。 如果您使用 Jetpack Compose
如果您使用 Kotlin 符号处理 (KSP),请参阅KSP 快速入门了解设置信息,并参阅KSP 版本了解可用版本。请注意,您必须使用与 Kotlin 版本匹配的 KSP 版本。例如,如果您使用的是 Kotlin 2.0.21,则可以使用任何以 2.0.21 开头的 KSP 插件版本,例如 2.0.21-1.0.25。您通常不需要升级 KSP 处理器(例如Room 编译器,它在您的构建文件中显示为 升级您正在使用的所有其他 Kotlin 编译器插件。Kotlin 编译器插件 API 在版本之间经常发生变化,插件必须使用兼容的 API。如果该插件列在编译器插件中,则必须使用与 Kotlin 编译器相同的版本。对于任何其他编译插件,请检查其文档以了解相应的映射。 请注意,那些没有与 Kotlin 编译器本身一起维护的编译器插件通常会经历发布延迟,因为它们需要等待编译器插件 API 稳定下来。在升级 Kotlin 之前,请检查您使用的所有编译器插件是否有相应的升级可用。 最后,在某些情况下,Kotlin 语言会发生变化,这要求您更新代码。如果您尝试使用实验性功能,这种情况最常发生。如果您的代码在升级 Kotlin 编译器后无法正常构建,请在Kotlin 发行说明中检查语言更改或运行时库中断。 |
Kotlin 编译器插件 |
如果您需要升级 Kotlin 编译器插件,请升级到正在使用的 Kotlin 的匹配版本。 大多数 Kotlin 编译器插件要么使用与 Kotlin 编译器相同的版本,要么以 Kotlin 编译器的所需版本开头。例如,如果插件版本是 2.0.21-1.0.25,则必须使用 2.0.21 版本的 Kotlin 编译器。 更改 Kotlin 编译器版本有时需要其他更改。 |
库 |
库是构建中最常升级的依赖项。您将在 Android Studio 编辑器中看到可用的升级,或者如果您使用某些依赖项工具和插件。 一些库指定使用该库所需的最小 一些库还指定了使用的最小 Kotlin 版本。将构建文件中的 Kotlin 版本更新为至少指定的版本。 |
Gradle |
有时,新版本的 Gradle 会弃用现有 API,并在将来的版本中删除这些 API。如果您开发 Gradle 插件,请尽快升级您的插件,尤其是在该插件是公共插件的情况下。 一些 Gradle 升级需要找到您使用的插件的新版本。请注意,这些插件在其开发过程中可能会滞后,因为它们会升级插件以匹配最新的 Gradle 插件 API。 要升级 Gradle
|
Gradle 插件 |
升级的 Gradle 插件有时会使用新的或更改的 Gradle API,这反过来又需要升级 Gradle,或者可能需要更改构建文件中的配置。无论哪种情况,您都会看到构建警告或错误以指示不兼容性。 升级插件时,请始终升级 Gradle。 |
Android SDK |
Android Studio 包含一个Android SDK 升级助手,可以帮助完成这些任务。 如果您使用助手或手动执行升级,请考虑以下事项 每个版本的 Android SDK 都包含新的功能和 API、错误修复和行为更改。Play 商店要求更新您的 在升级 Android SDK 之前,请仔细阅读发行说明。请密切关注行为更改部分,其中包括:
行为更改部分可能很长,但请密切关注,因为它通常包含您需要对应用程序进行的关键更改。 您必须升级 为了在开发过程中利用新的SDK功能并在构建过程中确保兼容性,请升级Android Gradle插件 (AGP) 和Android Studio。这些包括用于新SDK的新的和改进的工具。请参见Android API级别的工具的最低版本。 升级Android SDK时,请升级您使用的任何AndroidX库。AndroidX通常使用新的和更新的API来提高跨Android SDK版本的兼容性和性能。 |
Android Studio |
您通常可以随时升级Android Studio。您可能会看到提示您升级AGP或升级Android SDK的消息。强烈建议进行这些升级,但不是必需的。 如果您以后想使用Android Studio升级AGP或Android SDK,您可以在**工具**菜单中找到这些选项。 |
Java |
如果您的Android应用程序中包含Java源代码,您可能希望利用更新的Java API。 每个Android SDK版本都支持Java API的子集和语言特性。AGP使用称为反糖化的过程来提供对较低Android SDK版本的兼容性。 Android SDK发行说明指定支持哪个Java级别以及潜在的问题。由于Kotlin可以访问相同的Java API,因此其中一些问题也可能会影响Kotlin源代码。请务必仔细阅读发行说明的行为更改部分中出现的JDK API部分,即使您没有Java源代码。 JDK的使用在您的构建脚本的多个位置指定。有关更多信息,请参见Android构建中的Java版本。 |
升级分析
升级依赖项可能会带来风险,例如API和行为更改、新的使用要求、新的安全问题,甚至许可证更改。例如,您是否需要
- 更改代码以适应API更改?
- 添加新的权限检查?
- 为行为更改创建额外的测试或修改现有测试?
请考虑您已升级的依赖项已升级其自身的依赖项的版本。这很快就会变成大量的更改。
如果您使用Renovate或Dependabot之类的工具来自动化升级,请注意它们不会为您进行任何分析;它们会升级到最新的库版本。_不要假设这些类型的自动升级后一切都会正常工作_。
成功升级的关键在于升级分析
- 确定升级前后依赖项的差异。
- 检查每个更改并确定所涉及的风险。
- 减轻风险,或接受或拒绝更改。
确定依赖项差异
升级分析的第一步是确定依赖项如何变化。利用版本控制系统(VCS,例如Git)和Dependency Guard插件来快速查看更改。您的目标是创建_之前_和_之后_的快照并进行比较。
设置并创建您的第一个基线
在开始升级之前,请确保您的项目能够成功构建。
理想情况下,尽可能解决所有警告,或者创建基线以跟踪您已经看到的警告。
- Lint:检查您现有的lint警告并创建一个Android lint基线。
- Kotlin编译器
- 启用
-Werror
将所有警告都视为错误。请参见如何定义选项。 - 考虑使用Kotlin Warning Baseline或Kotlin Warnings Baseline Generator等插件。
- 启用
- 其他工具:如果您使用其他支持基线跟踪的静态分析工具(例如Detekt),请设置其基线。
这些警告基线使您更容易看到在升级依赖项时引入的新警告。
通过设置和运行Dependency Guard来创建依赖项基线。在您的gradle/libs.versions.toml版本目录中,添加
[versions]
dependencyGuard = "0.5.0"
[plugins]
dependency-guard = { id = "com.dropbox.dependency-guard", version.ref = "dependencyGuard" }
并将以下内容添加到您的应用程序的build文件中
Kotlin
plugins { alias(libs.plugins.dependency.guard) } dependencyGuard { configuration("releaseRuntimeClasspath") }
Groovy
plugins { alias(libs.plugins.dependency.guard) } dependencyGuard { configuration('releaseRuntimeClasspath') }
releaseRuntimeClasspath
配置是一个可能的目标,但如果您想使用不同的配置,请在您的build文件中不列出配置的情况下运行./gradlew dependencyGuard
以查看所有可用的配置。
设置完成后,运行./gradlew dependencyGuard
以在app/dependencies/releaseRuntimeClasspath.txt
中生成报告。这是您的基线报告。将其提交到您的版本控制系统 (VCS) 以保存。
请记住,Dependency Guard只捕获库依赖项的列表。您的构建文件中还有其他依赖项,例如Android SDK和JDK版本。在依赖项更改之前提交到您的VCS,可以让您的VCS差异也突出显示这些更改。
升级并与您的基线进行比较
拥有基线后,升级您想要测试的依赖项和其他构建更改。此时不要升级您的源代码或资源。
运行./gradlew lint
以查看新的lint警告或错误。解决任何重要问题,然后通过运行./gradlew lint -Dlint.baselines.continue=true
来更新您的警告基线。如果您已使用其他工具来捕获警告基线,例如Kotlin Warning Baseline或Kotlin Warnings Baseline Generator,请解决新的警告并更新其基线。
运行./gradlew dependencyGuard
来更新您的基线报告。然后运行您的VCS差异以查看非库更改。它可能包含比您想象的更多的库升级。
分析风险
一旦您知道发生了什么变化,请考虑每个升级库的潜在风险。这有助于集中您的测试或更深入地调查更改。为您的项目定义一组要分析的风险,以确保一致的分析。
一些注意事项
主要版本升级 |
主要版本号是否已更改? 当您看到此情况时,在查看以下任何注意事项时,请特别注意受影响的库。 如果您的代码使用任何实验性API(这通常需要您使用注释或build文件规范来选择加入),即使是次要或补丁版本更改,例如从1.2.3升级到1.3.1或1.2.3升级到1.2.5,也可能带来额外的风险。 |
非稳定API |
某些库版本可能包含非稳定API。这些通常是正在进行中的API,或者依赖于另一个不稳定的API。 虽然通常仅限于预览版,例如alpha版、dev版或实验版,但某些库包含标记为实验性或不稳定的API。 如果可能,请避免使用此类API。如果您需要使用它们,请务必记录您的使用情况,并注意以后版本中的更改或删除。 |
动态行为 |
某些库基于外部因素的行为不同。例如,与服务器通信的库取决于该服务器中的更改。
|
清单合并 |
发布为Android Archives (AAR) 的库可以包含合并到您的应用程序中的资源和清单。这些可以添加新的权限和Android组件,例如间接运行的活动或广播接收器。 |
运行时更新 |
某些库使用可以在您的应用程序控制之外更新的功能。库可以使用Play服务,该服务与Android SDK独立升级。其他库可能会绑定到独立更新的外部应用程序中的服务(通常使用AIDL)。 |
您跳过了多少个版本? |
您等待升级库的时间越长,潜在的风险就越大。如果您看到版本发生重大变化,例如从1.2.3到1.34.5,请特别注意此库。 |
迁移指南 |
检查库是否有迁移指南。这可以大大减少您的风险分析和缓解规划。 请注意,此类指南的存在是一个很好的指标,表明开发人员已专注于兼容性并考虑了您的升级缓解措施。 |
发行说明 |
查看每个已更改库的发行说明(如果提供)。查找中断更改或新要求的指示,例如添加的权限。 |
自述文件 |
某些库的自述文件会注明潜在风险,尤其是在库未提供发行说明的情况下。查找_已知问题_,尤其是已知的安全问题。 |
检查已知漏洞 |
Play SDK索引跟踪许多流行SDK的漏洞。Play控制台报告您是否使用具有已知漏洞的列出SDK之一。在Android Studio中编辑build文件时,IDE会检查SDK索引并标记使用易受攻击的库版本的情况。 美国国家标准与技术研究院 (NIST) 维持着一个大型的国家漏洞数据库 (NVD)。Dependency Check Gradle插件会根据NVD检查您使用的依赖项。 要使用Dependency Check,请申请NVD API密钥,设置Gradle插件,然后运行 |
版本冲突 |
版本是否按预期解析?查找冲突,尤其是在主要版本差异方面。有关如何查找冲突的详细信息,请参见Gradle依赖项解析。特别是在 如果可能,请与依赖项的作者合作以消除其依赖项的冲突。如果您的公司允许,请为库贡献更改(上游),以帮助提高库的兼容性。 |
检查许可证 |
升级库时查找许可证更改。库本身可能会更改为不再与您的应用程序或库兼容的许可证。新的传递依赖项也可能引入不兼容的许可证。有关检查依赖项中当前许可证集的详细信息,请参见验证许可证。 |
维护和 |
对于具有公共存储库的库
|
开源与闭源 |
如果是开源库,调试问题(无论问题出在你的代码中还是库代码中)都更容易。 尽量减少闭源依赖,并在评估过程中进行额外审查。是否存在适合您用例的良好替代方案?闭源库有哪些服务等级协议?如果您选择使用闭源依赖项,请准备好编写额外的测试用例以帮助限制风险。 |
运行构建
构建您的项目。查找新的错误或警告。如果您可以确定哪个库导致了这些错误或警告,请将其记为升级该库的风险。
如果您看到任何新的弃用警告,请将其添加为产生这些警告的库的特定风险。这些可以在以后的版本中删除。如果您想继续使用该库,请花时间从使用弃用的 API 转换为其替代品,或者记下弃用信息,以便关注这些函数以及它们是否会在以后被删除。
使用 lint 检测 API 问题
Android lint 可以捕获应用程序中的许多问题,包括一些由于更改依赖项版本或 Android SDK 版本而导致的问题。例如,如果您升级您的compileSdk
并使用其新的 API,lint 会报告在之前的 SDK 版本中不可用的那些 API。
Lint 在 Android Studio 编辑器中运行,在您进行更改时报告问题。但是,除非您使用build
或lint
目标,否则它通常不会作为 Studio 中构建的一部分运行,也不会在您运行命令行构建时运行。
如果您使用持续集成 (CI),请在您的 CI 构建中(至少在您的夜间构建中)运行gradlew build
或gradlew lint
以捕获这些类型的错误。
如果您不使用 CI,请确保至少偶尔运行gradlew lint
。
特别注意 lint 错误和警告。一些库附带自己的 lint 检查,有助于确保正确使用其 API。某些库的新版本包含新的 lint 警告和错误,导致在构建时出现新的报告。
降低风险
确定升级风险后,决定如何降低这些风险。
- 接受一些风险。一些风险足够低,可以接受,尤其是在升级时间和资源有限的情况下。
- 彻底拒绝一些风险。有些升级可能感觉风险太大,尤其是在您目前没有足够的时间或资源来降低这些风险的情况下。如果需要进行分类,请重点关注解决您遇到的错误或所需的新功能的升级。
- 降低剩余风险
- 考虑将升级批量处理成更小、更独立的更改集。这降低了整体风险并允许部分回滚。
- 详细调查更改。
- 测试您的应用程序 以检查意外更改。根据需要添加新的测试,以增强对升级的信心。
- 发现可疑之处时,查看源代码(如果可用)。
- 在您的源代码或构建中进行必要的更改。
记录您的决策。如果升级带来的风险在运行应用程序时成为问题,则记录您的风险分析可以减少必要的错误分析。
验证许可证
库开发者许可您使用这些库。您必须遵守许可证条款,否则您将无法使用该库。一些许可证非常宽松,通常只需要对库进行归属,并将许可证文本显示给最终用户。有些则被认为是“病毒式”的;如果您使用这些库,则必须将相同的许可证应用于您的应用程序或库。
许可证可能会随着任何版本的发布而更改。每次升级时,都应验证您使用的依赖项的许可方式是否与您的应用程序或库兼容。
如果许可证不兼容(或已更改为不再兼容),则您无法使用该版本的库。您可以:
- 联系库所有者,并请求继续使用现有许可证或双重许可,以继续允许使用旧许可证。
- 与您的法律团队合作,确定您是否可以更改您的许可证以使其兼容。
- 查找具有兼容许可证的另一个库,并根据需要修改您的应用程序。
- 派生最后兼容版本的库(如果该许可证允许派生作品并且更改不是追溯性的),并进行您自己的更改。