再见JCenter,将你的开源库发布到MavenCentral上吧

1,482 阅读11分钟

前言

关于 JCenter 废弃这件事情,相信许多朋友早就已经知道了。我在几个月前也专门写过一篇文章分析 JCenter 废弃事件的前前后后,感兴趣的朋友可以去阅读下这篇文章 浅谈 JCenter 即将被停止服务的事件

在上面这篇文章当中提到了几个比较关键的点:

  1. 自 2021 年 3 月 31 日之后,JCenter 就不再接受任何新库的提交。

  1. 自 2022 年 2 月 1 日之后,JCenter 将停止提供库的下载服务。

  1. Google 会在其 Android 开发者官网发布如何将开源库从 JCenter 迁出的方案。

当时整体的计划是这个样子的,然后几个月时间过去了,真是不得不说计划永远赶不上变化。

变化

首先,Google 修改了 Android 开发者官网的声明,没有再提到会给出迁出方案。只是告知开源库的发布者,以后发布库建议都发布到 MavenCentral 上。并告知开源库的使用者,你得自己去找这些库具体在哪里。

Google 的这波操作可真是把锅甩的干干净净,JCenter 废弃的事情与 “我” 再无关系,那是第三方开发者与 JCenter 之间的事情。

当时我看到 Google 修改声明之后心想,那这老库的迁移怎么办啊,Google 是完全不管了。

不过再仔细一看,我才发现,原来 JCenter 也改了声明。在 JCenter 的最新声明中,2022 年 2 月 1 日之后停止下载服务的那一条被删除了。也就是说,虽然 JCenter 不再允许开发者向其提交新的库,但是已经上传的老库会继续提供下载服务,这样也就不需要对它们做迁移了。

不知道为什么 JCenter 会改变态度做出这种善事,我猜测难不成是 Google 跟他们私下里进行了什么协商?不过不管怎么说,这对于开源库的开发者来说都是一件好事情,意味着老库的问题我们不需要再考虑了。

Google 已经给出了其官方态度,建议开发者以后发布库都发布到 MavenCentral 上。

官方的态度其实是很重要的,因为以前 JCenter 也是这样被 Google 扶正的(结果 Google 被坑惨了),不然 JCenter 也无法在 Android 领域产生这么大的影响力。

如果你现在用最新版的 Android Studio 来创建一个新的项目,你会发现 build.gradle 文件中仓库的声明变成了这样:

allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter() 
    }
}

可以看到,mavenCentral() 仓库成了创建项目时的默认仓库,而 jcenter() 仓库被标为了废弃。

许多国内的开发者可能会觉得 MavenCentral 太麻烦了,远不如 JitPack 用起来简单。

然而 JitPack 的问题就是并没有被 Google 官方推荐,你如果将库发布到 JitPack 上,开发者想要使用你的库,还得要额外引入一下 JitPack 的仓库才行,这无疑就增加了使用成本。

因此,即使是麻烦,我仍然建议广大开发者们要将自己的开源库发布到 MavenCentral 上。

相比于 JCenter,MavenCentral 的发布标准要远远高得多。不光是操作更麻烦的问题,而且 MavenCentral 还会对你是否拥有这个包路径所对应的域名进行检查。

比如你提交了一个库,它的包路径格式如下:

com.example.test:library:1.0.0

那么你就必须要拥有 example.com 这个域名才行。

相比之下,JCenter 就完全不检查你是否真的拥有这个域名,谁先提交了使用这个包路径的库,这个包路径就是谁的了。

另外,注册自己的域名是要花钱的,如果你不想花钱的话也可以借助 GitHub 来完成,但是这样你的包路径就必须以 io.github 为前缀,而不能使用自定义的包路径了。

本篇文章介绍的是使用自己的域名来提交到 MavenCentral 的方式,如果你想要了解使用 io.github 域名的方式,可以参考这篇文章 发布 Android Lib 到 Maven Central

那么不用多说,域名肯定是要自己先准备好的。我在阿里云上注册了一个叫 guolindev.com 的域名,因此我就可以使用以 com.guolindev 为前缀的包路径了。

接下来访问以下地址去注册一个 Sonatype 账号:

issues.sonatype.org/secure/Dash…

注册完之后重新访问该地址即可进入 Sonatype Dashboard 界面。

现在点击顶部工具栏上的 Create 按钮创建一个工单:

这个工单虽然看上去要填很多项内容,但其实还是非常简单的,我这里贴一下我当初填写的一个工单截图:

我们只需要填写带星号的必填项即可。

  • Project 和 Issue Type 保持默认选项,不用做修改。
  • Summary 可以随便填,这里我填写的是项目名称。
  • Group Id 非常重要,决定着库的包路径是什么。前缀使用你刚才申请好的域名的倒排方式,后面可以自定义一些与库名相关的路径。
  • Project URL 填写该项目的 Github 地址。
  • SCM url 只需要在上面的 Github 地址后面加上. git 后缀即可。

点击 Create 完成工单创建。

创建完工单之后需要等待工作人员审核,我测试下来非工作时间是没人审核你的工单的。所以如果你是在周末创建的工单,那么可能需要等待两到三天的时间才会有人处理。

有工作人员处理你的工单之后,他会在你的工单里留下一条评论,如下图所示:

这条评论的意思就是,你要证明刚才你在 Group Id 里填写的包路径所对应的域名是你的。

证明的方式就是,在你的域名中添加一条类型为 TXT 的解析,并将它指向你这条工单的 URL 地址。

如果你的域名是在阿里云注册的话,可以到域名管理界面,对着域名点击解析,然后按下图的示例添加解析记录即可:

添加完解析记录后,你需要在工单里回复一下,可以直接简单评论一句 Done 即可。这样工作人员会去验证你添加的解析记录是否已生效,验证没有问题之后,将会在评论里告诉你申请已通过:

从评论里得知,我们现在已经有权限向 s01.oss.sonatype.org 这个地址发布库了。

MavenCentral 还要求,所有发布的库都必须使用 GPG 来进行签名才行,所以接下来我们就进行这个操作。

GPG 在一些 Linux 系统上是内置的,如果你使用的 Linux 系统没有内置的话可以通过以下命令进行安装:

sudo apt install gnupg

Mac 系统可以借助 HomeBrew 进行安装,命令如下:

brew install gpg

Windows 系统需要访问下面的地址手动下载安装:

www.gnupg.org/download/

安装完成之后,输入以下命令创建密钥:

gpg --full-generate-key

接下来会弹出一系列的选项让你选择,比如密钥的类型,密钥的长度,密钥过期时间等。如果没有什么特殊需求的话,一路点击回车,使用默认选项就好了。

除此之外,还会要求你填写姓名、邮箱等内容,以及为这个密钥设置密码。

以上内容都填写完成之后,你就可以看到你创建的密钥了:

紧接着,我们需要把刚刚创建好的密钥上传到 GPG 服务器。这样 MavenCentral 到时候可以从 GPG 服务器上拿到我们的密钥,从对上传的包进行验证。

上传命令如下:

gpg --keyserver hkp://pgp.mit.edu --send-keys C37AF927

注意,最后 send-keys 后面使用的密钥 ID 是你刚刚创建的密钥 ID 的最后 8 位。这里一定要使用最后 8 位,我之前因为使用了完整的密钥 ID,结果一直出现奇奇怪怪的错误。

最后一步,执行以下命令生成私钥文件:

gpg --export-secret-keys  -o 文件路径/secring.gpg

这个私钥文件一定要在你本地保存好,后面提交库的时候还需要用到它。

以上所有步骤全部完成之后,下面就可以开始发布我们编写的开源库了。

发布

为了让发布过程变得更加简单,我使用了 gradle-maven-publish-plugin 这样一个第三方开源插件。当然如果你直接使用官方的 maven-publish 插件也是可以实现同样的功能的,只是得额外写不少代码才行。

gradle-maven-publish-plugin 插件的开源库地址是:

github.com/vanniktech/…

这个库的使用方法非常简单,将以下代码复制粘贴到你要发布的开源库所在模块的 build.gradle 文件的最底部即可:

...

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.vanniktech:gradle-maven-publish-plugin:0.17.0'
    }
}

allprojects {
    plugins.withId("com.vanniktech.maven.publish") {
        mavenPublish {
            sonatypeHost = "S01"
        }
    }
}

apply plugin: "com.vanniktech.maven.publish"

接来下打开项目根目录下的 gradle.properties 文件,并且按照下面的模板填入如下内容:

GROUP=com.guolindev.glance
POM_ARTIFACT_ID=glance
VERSION_NAME=1.0.0

POM_NAME=Glance
POM_DESCRIPTION=A simple and handy Android database debugging library.
POM_INCEPTION_YEAR=2020
POM_URL=https://github.com/guolindev/Glance/

POM_LICENSE_NAME=The Apache Software License, Version 2.0
POM_LICENSE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENSE_DIST=repo

POM_SCM_URL=https://github.com/guolindev/Glance/
POM_SCM_CONNECTION=scm:git:git://github.com/guolindev/Glance.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://github.com/guolindev/Glance.git

POM_DEVELOPER_ID=guolindev
POM_DEVELOPER_NAME=Lin Guo
POM_DEVELOPER_URL=https://github.com/guolindev/

signing.keyId=密钥ID的后8signing.password=密钥密码
signing.secretKeyRingFile=私钥文件路径

mavenCentralUsername=Sonatype账号
mavenCentralPassword=Sonatype密码

这个模板的前三项决定着你的开源库的包路径是什么,比如按照我上面的写法,那么这个开源库的包路径就是:

com.guolindev.glance:glance:1.0.0

其他几项大多是一些说明型的内容,根据自己的实际情况填写就可以了。

最后密钥部分要填写你刚才创建的公钥 ID 和密码,以及私钥的文件路径,另外还要填写 Sonatype 的账号密码。

由于我们在这个文件当中填写了很多隐私内容,一定要记得将它排除在版本控制之外。

现在,我们可以通过在 Android Studio 右侧工具栏的 Gradle 页签当中找到 publish 这个任务,双击执行即可将这个库发布出去。

如果一切顺利的话,就应该能在控制台中看到库已经发布成功了。

但是到这里还没完。

需要知道的是,我们刚才并没有将库发布到 MavenCentral,MavenCentral 也不允许我们直接将库发布上去。

回顾一下一开始创建的工单,工作人员回复我们的是什么?

可以看到,我们只是可以向 s01.oss.sonatype.org 这个地址发布库,而这并不是 MavenCentral。

另外我们刚才在 build.gradle 文件中编写的发布脚本也证实了这一点:

allprojects {
    plugins.withId("com.vanniktech.maven.publish") {
        mavenPublish {
            sonatypeHost = "S01"
        }
    }
}

这里将 sonatypeHost 指定成了 S01,而 S01 指的就是将库发布到 s01.oss.sonatype.org。

那么要如何才能将库发布到 MavenCentral 呢?接下来我们还需要做一下同步操作。

访问以下网址,并使用你的 Sonatype 账号密码登录 (登录按钮在页面右上角):

s01.oss.sonatype.org/

登录成功之后,页面的左侧边栏当中将会多出一个 Staging Repositories 选项:

点击该选项,你就能看到刚刚发布成功的开源库了:

现在我们需要将这个库同步到 MavenCentral 仓库。操作方法是,先勾选中这个仓库,然后点击 Close 按钮关闭仓库,并在弹出的确认窗口中点击 Confirm。

Close 完毕之后,刷新界面,你会发现 Release 按钮就变成可点击的状态了:

点击 Release 按钮,并在弹出窗口中点击 Confirm,这样就可以将这个开源库同步到 MavenCentral 上了。

不久之后,你会在之前创建的工单界面看到一条新的留言:

这是在告诉我们,同步工作已经开始了,通常大概需要 30 分钟左右的时间。但是如果想要在 search.maven.org 中可以搜到我们提交的仓库,最多可能需要 4 小时之久。

我并没有具体去验证一下同步到底需要多长时间,反正我是点击了 Release 按钮之后,第二天再到 search.maven.org 中去搜索,已经可以找到昨天提交的库了:

提交完成之后,想要在项目中引用这个库的话,只需要这样写即可:

dependencies {
    implementation 'com.guolindev.glance:glance:1.0.0'
}

和之前使用 JCenter 仓库的写法并无差别。

到这里,我们就把将开源库发布到 MavenCentral 的所有流程都走了一遍。只要跟着这些流程去操作,相信大家都可以成功将库发布到 MavenCentral 上。