发布变体可让您为用户创建更自定义的体验。配置发布变体可让您发布不同的构建变体,每个变体都有其自己的属性。
发布库的多个构建变体可让您的用户根据自己的需求选择合适的特性。例如,您可以为 调试与发布 构建类型发布不同的工件。调试发布工件可能包含额外的日志记录代码和不同的依赖项以启用此额外的日志记录。
在继续操作之前,请确保您已 准备发布库。
使用 Gradle 模块元数据
为了发布库的变体,您必须使用 Gradle 模块元数据 (GMM)。GMM 描述您的发布并维护 支持变体的依赖项管理。默认情况下,GMM 会与您的库一起发布。
使用 GMM 的优势包括
- 如果您将 GMM 与 Gradle 6.0 或更高版本一起使用,则可以发布多个发布变体或多个工件,每个工件都有其自己的属性和依赖项。如果您使用 Maven 的 POM 文件 而不是 GMM,则只能发布一个工件。如果您使用 POM 文件,则可以使用分类器发布其他工件,但其他工件不能有自己的依赖项。
- Gradle 会自动为编译和运行时创建一个变体,每个变体都有其自己的依赖项。您可能会为编译和运行时发布一个变体,以便使用者可以根据使用库的时间进行选择。GMM 允许使用者根据已发布库对
api
、implementation
或compileOnly
/runtimeOnly
的使用情况查看不同的编译和运行时依赖项。有关依赖项的完整列表,请参阅 依赖项配置。即使您发布单个发布变体,此功能也可用。 - 使用测试夹具时,您可以发布一个带有特殊元数据或 功能 的附加变体,让使用者可以选择它。即使您发布单个发布变体,此功能也可用。
了解发布变体
要了解发布变体的工作原理,熟悉 Gradle 的 基本发布步骤 会很有帮助。以下是一些发布的关键概念
- 构建变体:Gradle 用于构建库的配置,它是构建类型和产品风格的交叉积。要了解更多信息,请参阅 Android 构建词汇表。
- 工件:构建生成的文
- 发布变体:具有关联属性、特性和依赖项的工件。请注意,Gradle 将发布变体称为变体。但是,在这些文档中,它们被称为发布变体,以将其与构建变体区分开来。
- 属性 (Attribute):Gradle 使用属性来识别和选择发布变体,当存在多个选项时。例如,
org.gradle.usage=java-api
和org.gradle.jvm.version=11
是变体属性。 - 软件组件 (Software component):一个 Gradle 对象,可以包含一个或多个发布变体,并发布到一组 Maven 坐标 (
groupdId:artifactId:version
)。它通过Project.getComponents()
在 Gradle 的 DSL 中暴露。 - 发布 (Publication):发布到存储库并供使用者使用的内容。发布包含一个软件组件及其元数据——例如,其标识 (
groupId:artifactId:version
)。
Android Gradle 插件 (AGP) 7.1 引入了一种领域特定语言 (DSL) 来控制发布过程中使用哪些构建变体以及忽略哪些构建变体。DSL 允许您创建 SoftwareComponent
的实例,这些实例包含以下两者之一:
- 来自一个构建变体的一个发布变体
- 来自多个构建变体的多个发布变体
在创建具有多个发布变体的软件组件时,AGP 会在每个变体上设置属性,以便使用者选择他们需要的适当变体。这些属性直接来自用于创建构建变体的构建类型和风味。创建具有单个发布变体的组件不需要属性,因为不需要区分。
创建具有单个发布变体的软件组件
以下代码片段配置了一个软件组件,该组件具有一个从 release
构建变体创建的单个发布变体,并添加源 JAR 作为辅助构件
Kotlin
android { publishing { singleVariant("release") { withSourcesJar() } } }
Groovy
android { publishing { singleVariant('release') { withSourcesJar() } } }
您可以创建多个组件,每个组件都具有单个发布变体,并以不同的 Maven 坐标分发它们。在这种情况下,不会在发布变体上设置属性。您无法通过查看发布元数据来判断此发布变体来自 release
构建变体。由于只涉及一个发布变体,因此不需要消除歧义。
创建具有多个发布变体的软件组件
您可以选择所有或一部分构建变体以放入单个软件组件中。AGP 自动使用构建类型名称、产品风味名称和产品风味维度名称来创建属性,以便使用项目能够区分它们。
要将所有构建变体发布到单个组件中,请在模块级 build.gradle
文件的 multipleVariants{}
块中指定 allVariants()
Kotlin
android { publishing { multipleVariants { allVariants() withJavadocJar() } } }
Groovy
android { publishing { multipleVariants { allVariants() withJavadocJar() } } }
这将创建一个名为 default
的单个组件。要将组件命名为其他名称,请使用 multipleVariants({name})
。在这种情况下,所有构建类型和产品风味维度都用作属性。
您还可以使用 includeBuildTypeValues()
和 includeFlavorDimensionAndValues()
来选择发布哪些变体
Kotlin
android { publishing { multipleVariants("custom") { includeBuildTypeValues("debug", "release") includeFlavorDimensionAndValues( dimension = "color", values = arrayOf("blue", "pink") ) includeFlavorDimensionAndValues( dimension = "shape", values = arrayOf("square") ) } } }
Groovy
android { publishing { multipleVariants('custom') { includeBuildTypeValues('debug', 'release') includeFlavorDimensionAndValues( /*dimension =*/ 'color', /*values =*/ 'blue', 'pink' ) includeFlavorDimensionAndValues( /*dimension =*/ 'shape', /*values =*/ 'square' ) } } }
在此示例中,自定义组件包含构建类型的 (debug
、release
)、维度 color
的 (blue
、pink
) 和维度 shape
的 (square
) 的所有组合。
必须列出所有风味维度,即使您只发布了一个维度的值,以便 AGP 知道每个维度的使用值。
下表列出了生成的发布变体及其关联的属性。
变体 | 属性 |
---|---|
blueSquareDebug | com.android.build.api.attributes.BuildTypeAttr ="debug" com.android.build.api.attributes.ProductFlavorAttr:color ="blue" |
blueSquareRelease |
com.android.build.api.attributes.BuildTypeAttr="release" |
pinkSquareDebug |
com.android.build.api.attributes.BuildTypeAttr="debug" |
pinkSquareRelease |
com.android.build.api.attributes.BuildTypeAttr="release" |
实际上,发布了更多变体。例如,上述每个变体都发布了两次,一次用于编译,一次用于运行时,具有不同的依赖项(基于声明的依赖项是否使用 implementation
或 api
)以及属性 org.gradle.Usage
的不同值。但是,这两个变体的构件 (AAR 文件) 是相同的。
有关更多信息,请参阅 publishing
API 文档。
发布多风味库的兼容性问题
使用 AGP 7.0 或更低版本的项目无法使用使用 AGP 7.1 或更高版本发布的多风味库。这是由于 AGP 7.1 中产品风味维度的属性名称从 dimensionName
更改为 com.android.build.api.attributes.ProductFlavor:dimensionName
而导致的已知问题。根据您的项目设置,您可以使用 missingDimensionStrategy
在旧版变体 API 中 来解决此问题。
例如,假设您的应用程序项目只有一个版本产品风味维度
Kotlin
android {
applicationVariants.forEach { variant ->
val flavor = variant.productFlavors[0].name
val attributePrefix = "com.android.build.api.attributes.ProductFlavor"
val dimensionName = "version"
variant.missingDimensionStrategy("$attributePrefix:$dimensionName", flavor)
}
}
Groovy
android {
applicationVariants.forEach { variant ->
def flavor = variant.getProductFlavors()[0].name
def attributePrefix = "com.android.build.api.attributes.ProductFlavor"
def dimensionName = "version"
variant.missingDimensionStrategy("$attributePrefix:$dimensionName", flavor)
}
}