又一个发布 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!

相关推荐
Dingdangr3 小时前
Android中的Intent的作用
android
技术无疆3 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
GEEKVIP3 小时前
Android 恢复挑战和解决方案:如何从 Android 设备恢复删除的文件
android·笔记·安全·macos·智能手机·电脑·笔记本电脑
老王笔记9 小时前
Maven下载安装
maven
Jouzzy10 小时前
【Android安全】Ubuntu 16.04安装GDB和GEF
android·ubuntu·gdb
极客先躯10 小时前
java和kotlin 可以同时运行吗
android·java·开发语言·kotlin·同时运行
Good_tea_h13 小时前
Android中的单例模式
android·单例模式
litGrey14 小时前
Maven国内镜像(四种)
java·数据库·maven
尘浮生18 小时前
Java项目实战II基于Java+Spring Boot+MySQL的大学城水电管理系统(源码+数据库+文档)
java·开发语言·数据库·spring boot·后端·mysql·maven
尘浮生18 小时前
Java项目实战II基于Java+Spring Boot+MySQL的保密信息学科平台系统(源码+数据库+文档)
java·开发语言·数据库·spring boot·后端·mysql·maven