上传 Android 库到 MavenCentral

上传 Android 库到 MavenCentral

最近在学习 Android 中的注解处理器,仿写了一个 ActivityStarter 来解决 Activity 启动传参问题,为了方便使用决定将库上传到远程仓库,之前都是上传到 JCenter 的,也有现成的插件,十分方便,但目前 JCenter 已不能发布新的项目,所以打算将项目上传到 MavenCentral,以此文章来记录上传的流程。

JCenter 服务更新

JFrog(这家公司维护着很多 Android 项目使用的 JCenter 工件库)已于 2021 年 3 月 31 日将 JCenter 设为只读代码库。根据公告,JCenter 将无限期地提供现有工件供用户下载。

在 JCenter 上发布工件的开发者应该将其软件包迁移到新的托管服务,如 Maven Central

使用 JCenter 中依赖项的开发者将需要找到相应依赖项的更新后版本所在的新位置。

注册 Sonatype 账号

注册地址:https://issues.sonatype.org/secure/ForgotLoginDetails.jspa

创建问题

注册好账号之后,需要创建一个问题

创建Sonatype 问题_1

创建Sonatype问题_2

创建Sonatype 问题_3

根据提示填写好基本信息之后,点击创建就可以了。

注:Group Id 填写时需要确认是否为自己的域名,如 com.xxx,则拥有此域名,如果没有个人域名,则可使用 GitHub 的域名,io.github.用户名,如:io.github.qihuan92

创建好问题之后,就可以根据问题详情页中的注释来进行操作了,比如我的域名填写的是 GitHub 的,所以需要创建一个名称为问题编号的仓库,后边等待问题关闭就可以了。

创建Sonatype问题_4

项目 Gradle 配置

上传 Gradle 配置文件

在根项目创建一个 publish.gradle 文件

apply plugin: 'maven-publish'

def isAndroidProject = project.hasProperty('android')

task sourcesJar(type: Jar) {
archiveClassifier.set('sources')
if (isAndroidProject) {
from android.sourceSets.main.java.srcDirs
} else {
from sourceSets.main.allSource
}
}

if (isAndroidProject) {
task javadoc(type: Javadoc) {
options.encoding = 'UTF-8'
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
android.libraryVariants.all { variant ->
if (variant.name == 'release') {
owner.classpath += variant.javaCompile.classpath
}
}
}
} else {
javadoc {
options.encoding = 'UTF-8'
}
}

task javadocJar(type: Jar, dependsOn: javadoc) {
archiveClassifier.set('javadoc')
from javadoc.destinationDir
}

afterEvaluate {
publishing {
repositories {
maven {
name = "OSSRH"
url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
credentials {
username = project.ossrhMavenUser // sonatype 用户名
password = project.ossrhMavenPassword // sonatype 密码
}
}
}

publications {
release(MavenPublication) {
// 如果判断是否为 Android Module
if (isAndroidProject) {
from components.release
} else {
from components.java
}
artifact(sourcesJar)
artifact(javadocJar)

groupId project.publishGroupId // groupId
artifactId project.artifactId // artifactId
version project.activityStarterVersionName // 版本号

pom {
name = project.artifactId // artifactId
description = 'ActivityStarter' // 项目描述
url = 'https://github.com/qihuan92/ActivityStarter' // 项目地址
// 许可相关配置
licenses {
license {
name = 'ActivityStarter License'
url = 'https://github.com/qihuan92/ActivityStarter/blob/master/LICENSE'
}
}
// 开发者信息
developers {
developer {
id = 'qihuan'
name = 'qihuan'
email = 'qihuan92@126.com'
}
}

// scm 配置
scm {
connection = 'scm:git:github.com/qihuan92/ActivityStarter.git'
developerConnection = 'scm:git:ssh://github.com/qihuan92/ActivityStarter.git'
url = 'https://github.com/qihuan92/ActivityStarter/tree/master'
}
}
}
}
}
}

然后在需要上传的 module 的 builder.gradle 中添加依赖

ext {
artifactId = 'activitystarter-runtime' // TODO 填写需要上传项目的 artifactId
}
apply from: rootProject.file('publish.gradle')

签名配置

生成一个 GPG 秘钥

因为上传 MavenCentral 需要发布者签名验证,所以需要生成一个 GPG 秘钥。可以从 gnupg.org 下载对应的客户端,MacOS 的下载地址为 GPG Suite ,Windows 为 Gpg4win

打开客户端后点击创建秘钥,选项如下:

创建GPG秘钥_1

创建完成之后就会提示上传到秘钥服务器了。

发布项目时需要一个秘钥的 Key,可通过以下命令生成,注 XXX 为指纹的后八位

gpg --export-secret-keys XXX | base64

配置签名信息到 publish.gradle 文件

apply plugin: 'signing'

signing {
useInMemoryPgpKeys(
project.signingKeyId, // 指纹的后八位
project.signingKey, // 导出的 base64 指纹信息
project.signingPassword, // 签名的密码
)
sign publishing.publications
}

完整的 publish.gradle 文件

apply plugin: 'maven-publish'
apply plugin: 'signing'

def isAndroidProject = project.hasProperty('android')

task sourcesJar(type: Jar) {
archiveClassifier.set('sources')
if (isAndroidProject) {
from android.sourceSets.main.java.srcDirs
} else {
from sourceSets.main.allSource
}
}

if (isAndroidProject) {
task javadoc(type: Javadoc) {
options.encoding = 'UTF-8'
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
android.libraryVariants.all { variant ->
if (variant.name == 'release') {
owner.classpath += variant.javaCompile.classpath
}
}
}
} else {
javadoc {
options.encoding = 'UTF-8'
}
}

task javadocJar(type: Jar, dependsOn: javadoc) {
archiveClassifier.set('javadoc')
from javadoc.destinationDir
}

afterEvaluate {
publishing {
repositories {
maven {
name = "OSSRH"
url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
credentials {
username = project.ossrhMavenUser
password = project.ossrhMavenPassword
}
}

maven {
name = "GitHubPackages"
url = "https://maven.pkg.github.com/qihuan92/ActivityStarter"
credentials {
username = project.githubMavenUser
password = project.githubMavenToken
}
}
}

publications {
release(MavenPublication) {
if (isAndroidProject) {
from components.release
} else {
from components.java
}
artifact(sourcesJar)
artifact(javadocJar)

groupId project.publishGroupId
artifactId project.artifactId
version project.activityStarterVersionName

pom {
name = project.artifactId
description = 'ActivityStarter'
url = 'https://github.com/qihuan92/ActivityStarter'
licenses {
license {
name = 'ActivityStarter License'
url = 'https://github.com/qihuan92/ActivityStarter/blob/master/LICENSE'
}
}
developers {
developer {
id = 'qihuan'
name = 'qihuan'
email = 'qihuan92@126.com'
}
}

scm {
connection = 'scm:git:github.com/qihuan92/ActivityStarter.git'
developerConnection = 'scm:git:ssh://github.com/qihuan92/ActivityStarter.git'
url = 'https://github.com/qihuan92/ActivityStarter/tree/master'
}
}
}
}
}
}

signing {
useInMemoryPgpKeys(
project.signingKeyId,
project.signingKey,
project.signingPassword,
)
sign publishing.publications
}

发布到 MavenCentral

相关命令

项目配置好之后就可以发布项目到 MavenCentral 了

# yourmodule 为需要上传的模块名
./gradlew yourmodule:publishReleasePublicationToOSSRHRepository

登录网页发布

执行上述命令成功后,就可以登录 https://s01.oss.sonatype.org 查看待发布的库了,如下图所示:

MavenCentral发布

在 Staging Repositories 页签可以看到刚刚上传的包,然后选中点击 Close 按钮,如果关闭成功,就可以点击 Release 按钮来发布项目了。

评论