又一个发布 Android 库到 Maven Central 的指南?

是的, 这是另一本关于如何将 Android artifacts发布到 Maven Central 的指南. 与其他指南不同的是, 它还包含了一些额外的"内容":

  • 使用 Kotlin DSL 编写 Gradle 文件.
  • 发布AAR文件artifacts.
  • 发布包含一个Source Jar 文件(hello withSourcesJar).
  • 发布包含一个 Javadoc Jar 文件(hello withJavadocJar ).
  • 该发布与CI/CD管道协同工作.
  • 我提到过这是Android专用吗?

对于那些不喜欢阅读的人, 以下是我使用所解释的发布机制的两个软件仓库:

Sonatype OSSRH

Maven Central 实际上只是多个仓库的门面. Sonatype OSSRH 就是这样一个仓库. 为了发布你的artifacts, 你需要在他们(或其他Release 仓库提供商)那里注册一个账户. 关于如何开设账户和正确配置账户, 有很多不错的文章. 我将在此引用这些文章, 然后就结束了(这是一个繁琐的过程, 所以请确保你有时间...):

所需插件

此时的假设是:

  • 你在 Sonatype OSSRH 有一个账户.
  • 你在 Sonatype OSSRH 上创建了一个仓库, 并已验证了你对仓库的所有权.
  • 你创建了用于签署artifacts的GPG 密钥对, 并已发布公钥和导出私钥.
  • 你已经有了一个带有 Kotlin DSL 构建文件(与 Groovy 构建文件相比)的应用程序 -> build.gradle.kts.

现在第一步是在构建文件中添加两个插件:

bash 复制代码
plugins {
    id("com.android.library")
    id("maven-publish")
    id("signing")
} 

发布

第二步是创建并配置 publishing 扩展, 将其添加到 gradle 构建文件中:

arduino 复制代码
afterEvaluate {
    publishing {
        publications {
            // here goes your configuration
        }
    }
}

afterEvaluate确保项目已被评估, 并可在配置块中访问.

配置包括三个步骤:

  1. 配置仓库
  2. 配置发布
  3. 签署artifacts
arduino 复制代码
afterEvaluate {
    publishing {
        publications {
            // 1. configure repositories
            // 2. configure publication
            // 3. sign the artifacts
        }
    }
}

仓库

这部分配置定义了目标仓库. 在我们的例子中, 它是 Sonatype OSSRH, 可以是Release库, 也可以是SNAPSHOT库.

目标仓库的确定基于版本名称. 后缀名为-SNAPSHOT的版本将上传到SNAPSHOT仓库.

发布

配置发布非常简单.

首先, 我们定义要发布的artifacts:

scss 复制代码
from(project.components["release"])
artifact(tasks.named<Jar>("withJavadocJar"))
artifact(tasks.named<Jar>("withSourcesJar"))

project.components["release"]是 Android 项目生成的artifacts, 对于 Android 库来说, 应该是一个 aar 文件. 另外两行将 Javadoc 和源码jar 文件声明为要发布的artifacts. 本文稍后将解释如何生成这两个artifacts.

配置的其余部分定义了 Maven POM 文件, 它是 Maven 项目(项目元信息)的 XML 表示形式.

需要配置的最重要属性是groupId , artifactIdversion (例如, 对于 com.android.tools.build:gradle:7.0.2, groupIdcom.android.tools.build , artifactIdgradle , version 显然是7.0.2). 所有其他属性都是可选参数, 用于定义软件许可证, 识别公司/开发者, 源代码等.

正如你所看到的, 这些属性都是从 project.properties 中读取的, 而 project.properties 是在其中一个 gradle.properties 文件(项目或库的特定属性文件)中定义的属性. 下面是这样一个属性文件的例子: github.com/1gravity/An....

请注意, 仓库的用户名和密码不是在项目属性文件中定义的, 而是应该在你的 ~/.gradle/gradle.properties 文件(~ 代表你的主目录)中定义, 这样凭据才不会提交到源代码控制中. 如果没有该文件, 则需要创建并添加凭据:

ini 复制代码
ossUsername=<your OSS user>
ossPassword=<your OSS password>

签名

对artifacts进行签名非常简单:

scss 复制代码
signing {
 sign(publishing.publications.getByName(publicationName))
 } 

签名插件使用你之前创建的密钥(请参阅 "你创建了用于签署artifacts的GPG 密钥对 , 并已发布公钥和导出私钥"). 该插件需要 private key 文件, keyIdpassword , 这些都是在~/.gradle/gradle.properties文件中定义的. 将此添加到文件中:

ini 复制代码
signing.secretKeyRingFile=/<user>/.gnupg/secring.gp
g
signing.keyId=<last 8 characters of your key id>
signing.password=<the password>

注意, ~/.gnupg/secring.gpg将不起作用, 因为 Android 无法将~解析为你的主目录.

就是这样. 如果你在项目目录下运行 ./gradlew publish, 它就会构建并向 Sonatype OSSRH 发布你的库. 你仍然需要手动关闭和发布库, 虽然这也可以自动完成, 但你应该熟悉手动过程: central.sonatype.org/publish/rel....

使用 CI/CD 签名

大多数构建管道以字符串形式读取秘密, 而不是从文件(如上文使用的 secretKeyRingFile)中读取. 虽然有一些方法可以将文件送入管道(关于 BitBucket 管道的描述可参见这里), 但这是一个相当繁琐的过程. 最好还是不要使用文件.

在本例中, 我们可以在创建签名任务前调用 useInMemoryPgpKeys 来使用内存中的 PGP 密钥和密码:

如果在本地编译, 这三个参数将从属性文件中读取, 因此请将这些值放入~/.gradle/gradle.properties文件中:

ini 复制代码
signingKeyId=<last 8 characters of your key id>
signingKeyPassword=<the password>
signingKey=<the key>

密钥需要装上铠甲, 即转换为完全由文本模式/ASCII 字符组成的文件加密表示. 它还需要去掉 gpg 对实际密钥的典型包装(- - -BEGIN PGP PRIVATE KEY BLOCK - - -部分).

使用此单行命令获取密钥值:

perl 复制代码
gpg --export-secret-keys --armor <KEY_ID> |grep -v '--' |grep -v '=.' |tr -d '\n'

要在构建管道中运行此功能, 需要在相应的秘密管理器中配置秘密. 对于 GitHub 来说是这样的:

在定义管道时, 你需要把秘密作为参数传递给 gradle/gradlew.

对于 GitHub Actions, 语法为:

ini 复制代码
./gradlew -PossUsername=${{ secrets.OSSRH_USERNAME }}

对于 BitBucket Pipeline, 语法为:

ini 复制代码
./gradlew -PossUsername=$OSSRH_USERNAME

withSourcesJar

在 Java 项目中, 有一种简单的方法可以为源代码和 Javadoc 创建 Jar 文件:

scss 复制代码
java {
    withSourcesJar()
    withJavadocJar()
} 

遗憾的是, 这在 Android 项目中行不通. 不过, 复制 withSourcesJar 非常简单:

c 复制代码
tasks {
    register<Jar>("withSourcesJar") {
        archiveClassifier.set("sources")
        from(android.sourceSets.getByName("main").java.srcDirs)
    }
} 

这将注册一个名为 withSourcesJar 的任务. 它会创建一个 Jar 文件(因此定义了 Jar 类型, 并使用 Android 源代码目录(android.sourceSets.getByName("main").java.srcDirs)作为 jar 文件的输入.

withJavadocJar

为 Javadoc 创建 jar 文件同样简单:

scss 复制代码
tasks {
    archiveClassifier.set("javadoc")
    dependsOn(named("withJavadoc"))
    val destination = named<Javadoc>("withJavadoc").get().destinationDir
    from(destination)
}

唯一的问题是, 我们需要先创建 Javadoc, 然后才能创建 jar 文件. 如上所示, 我们引用了名为 withJavadoc 的任务来创建实际文档.

总结一下

这就是全部代码:

该代码将在这里使用:

1gravity/Android-RTEditor/build.gradle.kts

以及这里:

1gravity/Android-ColorPicker/build.gradle.kts

Happy Coding! Stay GOLDEN!

相关推荐
咖啡の猫1 小时前
Android开发-常用布局
android·gitee
程序员老刘2 小时前
Google突然“变脸“,2026年要给全球开发者上“紧箍咒“?
android·flutter·客户端
Tans52 小时前
Androidx Lifecycle 源码阅读笔记
android·android jetpack·源码阅读
雨白2 小时前
实现双向滑动的 ScalableImageView(下)
android
峥嵘life3 小时前
Android Studio新版本编译release版本apk实现
android·ide·android studio
wangmengxxw4 小时前
Maven的介绍及基本使用
java·maven
studyForMokey5 小时前
【Android 消息机制】Handler
android
敲代码的鱼哇5 小时前
跳转原生系统设置插件 支持安卓/iOS/鸿蒙UTS组件
android·ios·harmonyos
翻滚丷大头鱼5 小时前
android View详解—动画
android
我是好小孩5 小时前
[Android]RecycleView的item用法
android