PAYATHON 2026

如何使用 libs.versions.toml 管理 Android build-Variants?

技术老齐

可以在 libs.versions.toml 中声明两组依赖,再在应用模块中定义 android5、android6 两个 product flavor,通过各自的 Implementation 配置引用对应版本。

libs.versions.toml 集中管理依赖坐标和版本,Android Gradle Plugin 则负责创建构建变体、设置 minSdk 和选择依赖。版本目录不会根据 Android API 级别自动切换版本。

1. 在版本目录中声明两组依赖

将 gradle/libs.versions.toml 改为:

[versions]
activityAndroid5 = "1.11.0"
activityAndroid6 = "1.13.0"
commonsIoAndroid5 = "2.7"
commonsIoAndroid6 = "2.22.0"

[libraries]
activity-android5 = { module = "androidx.activity:activity", version.ref = "activityAndroid5" }
activity-android6 = { module = "androidx.activity:activity", version.ref = "activityAndroid6" }

commons-io-android5 = { module = "commons-io:commons-io", version.ref = "commonsIoAndroid5" }
commons-io-android6 = { module = "commons-io:commons-io", version.ref = "commonsIoAndroid6" }

同一个 Maven 模块可以有多个别名,分别关联不同版本。例如,activity-android5 和 activity-android6 都指向 androidx.activity:activity。

Gradle 会把别名中的连字符转换为访问器层级。上面四条声明对应的访问器依次为:

libs.activity.android5
libs.activity.android6
libs.commons.io.android5
libs.commons.io.android6

放在默认位置的 gradle/libs.versions.toml 会自动导入,无须手动创建同名 libs catalog。参见 Gradle 版本目录文档。

2. 在应用模块中配置 product flavors

下面使用 Kotlin DSL。将配置合并到现有的 app/build.gradle.kts,保留项目已有的插件、namespace、compileSdk、targetSdk 等设置:

android {
    flavorDimensions += "platformApi"

    productFlavors {
        create("android5") {
            dimension = "platformApi"
            minSdk = 21
        }

        create("android6") {
            dimension = "platformApi"
            minSdk = 23
        }
    }
}

dependencies {
    add("android5Implementation", libs.activity.android5)
    add("android5Implementation", libs.commons.io.android5)

    add("android6Implementation", libs.activity.android6)
    add("android6Implementation", libs.commons.io.android6)

    // 两个 flavor 共用的其他依赖仍放在 implementation 中。
}

使用 add("配置名称", 依赖) 可以直接向动态创建的 flavor 配置添加依赖,无须由 Kotlin DSL 生成同名函数。

同时删除公共 implementation 中原有的 Activity 和 Commons IO 声明,避免它们与 flavor 专属依赖同时进入同一依赖图。

Android 的 build variant 由 product flavor 和 build type 组合产生。保留默认的 debug、release 时,会得到:

构建变体minSdkActivity 请求版本Commons IO 请求版本
android5Debug、android5Release211.11.02.7
android6Debug、android6Release231.13.02.22.0

android5、android6 是 flavor 名称,完整的构建变体名称还包含 build type。Android Gradle Plugin 支持按 flavor 声明依赖,参见 Android 构建变体配置文档。

如果项目已经定义了 flavor dimension,需要合并这组配置。多个维度会产生更多组合变体。

3. 代码仍然放在公共源码目录

如果只是依赖版本不同,可以继续共用源码,无须拆成两个应用模块或复制源码:

project/
├── gradle/
│   └── libs.versions.toml
├── settings.gradle.kts
└── app/
    ├── build.gradle.kts
    └── src/
        └── main/
            ├── AndroidManifest.xml
            ├── java/
            └── res/

两个 flavor 共用 src/main/,公共代码只能调用两组依赖都提供的 API。如果调用了新版本才有的方法,使用旧版本的变体会编译失败。出现实现差异时,再考虑增加 src/android5/、src/android6/。

仓库配置也要覆盖这两类依赖。项目中已经配置的 google() 和 mavenCentral() 可以继续使用:

// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
}

4. 构建并检查最终解析版本

同步 Gradle 后,可以在 Android Studio 的 Build Variants 窗口选择变体,也可以执行以下命令。这里假设应用模块名为 app:

./gradlew :app:assembleAndroid5Debug
./gradlew :app:assembleAndroid6Debug

还需要检查依赖树。版本目录声明的是请求版本,传递依赖或约束可能改变最终选择的版本。参见 Gradle 对版本目录与冲突解析的说明。

./gradlew :app:dependencies --configuration android5DebugRuntimeClasspath
./gradlew :app:dependencies --configuration android6DebugRuntimeClasspath

如果发现旧版本被升级,可以用下面的命令查找引入更高版本的依赖:

./gradlew :app:dependencyInsight \
  --configuration android5DebugRuntimeClasspath \
  --dependency androidx.activity:activity

dependencyInsight 会显示版本选择原因和相关依赖路径,具体用法见 Gradle 依赖诊断文档。

如果必须严格使用指定版本,可以将相应的版本声明改为:

[versions]
activityAndroid5 = { strictly = "1.11.0" }
commonsIoAndroid5 = { strictly = "2.7" }

用这两行替换原有条目。严格约束可能导致不兼容的依赖要求在解析阶段报错,需要继续排查并处理冲突来源。它也不能保证其他库调用的 API 一定存在。

5. 依赖版本与 Android 兼容性要分开确认

完成依赖分组后,还要确认应用能否在 API 21、API 23 上正常运行。这取决于完整依赖图和实际调用的 API。

Activity 的最低 API 与编译 SDK 是不同要求

Activity 官方发布说明在 1.12.0-alpha06 中就已记录默认 minSdk 从 API 21 提升到 API 23,不能把这一变化的起点理解为 1.12.2。

Activity 1.11.0 已使用 API 36 编译。即使应用要支持旧设备,构建时也需要满足依赖声明的 minCompileSdk 和 Android Gradle Plugin 要求,不能因此沿用旧的 compileSdk。参见 Activity 发布说明。

Commons IO 支持 Java 8,不等于保证支持某个 Android API

原注释中“2.7 是最后支持 Java 8 的版本”这一说法不准确。Apache 官方说明中,Commons IO 2.22.0 的最低要求仍是 Java 8。参见 Commons IO 发布记录。

Java 版本要求不能直接换算为 Android 最低 API。即使字节码可以处理,库内部调用的 Java 标准库 API 仍可能在旧版 Android 上不可用。需要结合实际调用路径,检查是否需要 core library desugaring,以及所需 API 是否在支持范围内。相关机制见 Android Java API 脱糖文档。

可以按需求保留 2.7 和 2.22.0 两组版本,并分别在 API 21、API 23 环境验证实际使用的功能。minSdk = 21 表示允许安装到 API 21 及更高版本,Gradle 不会在安装或运行时按设备系统版本重新选择依赖。

备注:内容仅供参考。