Android库发布到Maven Central超详细攻略

4,829 阅读7分钟

image.png

前言

最近写了一个自动化打包上传到蒲公英等三方平台,在飞书的群机器人中发送消息,解放双手,方便测试人员下载的项目,想发布到远程服务器供方便调用,但是记得JCenter已经宣布在2020年5月1日,停止新的库的提交(只能使用,不能再提交),在2022年2月21号以前,连库的解析服务也停止,所以,尝试将打包库发布到maven central上。

需要哪些工具

1: sonatype

2: nexus

3: Github

第一步 · Sonatype Jira配置

与jCenter一样,Maven Central是由sonatype运营的,那么首先需要去注册一个sonatype的账号并获得仓库使用许可。

注册

首先需要到issues.sonatype.org注册账号,界面如图:

image.png

填写邮箱、用户名、密码信息即可注册成功

注意:邮箱很重要,建议是你常用的邮箱,以便及时收到 Sonatypeissue 中的答复。

注册成功后再次回到登录页面,填写刚才注册的用户名和密码即可在Sonatype完成登陆,如下图。

image.png

注册需要填写邮箱(重要,请填写真实的邮箱)、名字、用户名(重要,用于登录)、密码(需要含符号、英文和数字的复杂密码),和验证码完成注册。

创建问题

按照图中所示,我们创建一个问题。

image.png

该步骤中唯一需要注意的地方就是 Group Id,填写错sonatype工作人员会给你提一个issue,有两种情况:

  • 无网站域名:使用 github 的子域名 io.github.username,比如我的 github 账号名是 Eegets,那么可以填写 io.github.eegets
  • 有网站域名:可以填写个人或公司域名,比如:com.eegets,另外,还需要在 DNS 配置中配置一个 TXT 记录来验证域名所有权,具体请看:central.sonatype.org/pages/produ…

创建以后,会有管理员处理你的这个issue,等待管理员回复你的issue,一般需要设置一步:在github上创建一个空的仓库,我的空仓库名为:OSSRH-75861。第二就是是否要修改groupId。

管理员回复我的如下图:

image.png

当该问题状态变为已解决,则证明我们sonatype项目已经完成了申请,如下图

image.png

第二步·Gradle配置

接下来打开你的项目,在项目根目录创建一个后缀为.gradle的文件「我创建的文件名为:publish-mavencentral.gradle」,如下:

该文件是通用的文件配置,直接copy修改里边的一些配置项即可

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

task androidSourcesJar(type: Jar) {
    classifier = 'sources'

    exclude "**/R.class"  //排除`R.class`
    exclude "**/BuildConfig.class"  //排除`BuildConfig.class`
}
//第 1 处
ext["signing.keyId"] = '' //签名的密钥后8位
ext["signing.password"] = ''  //签名设置的密码
ext["signing.secretKeyRingFile"] = '' //生成的secring.gpg文件目录
ext["ossrhUsername"] = ''  //sonatype用户名
ext["ossrhPassword"] = ''  //sonatype密码

File secretPropsFile = project.rootProject.file('local.properties')
if (secretPropsFile.exists()) {
    println "Found secret props file, loading props"
    Properties p = new Properties()
    p.load(new FileInputStream(secretPropsFile))
    p.each { name, value ->
        ext[name] = value
    }
} else {
    println "No props file, loading env vars"
}
publishing {
    publications {
        release(MavenPublication) {
            println("publish-maven Log-------> PUBLISH_GROUP_ID: $PUBLISH_GROUP_ID; PUBLISH_ARTIFACT_ID: $PUBLISH_ARTIFACT_ID; PUBLISH_VERSION: $PUBLISH_VERSION")
            // The coordinates of the library, being set from variables that
            
            //第 2 处
            groupId PUBLISH_GROUP_ID
            artifactId PUBLISH_ARTIFACT_ID
            version PUBLISH_VERSION

            // Two artifacts, the `aar` and the sources
            artifact("../plugin/com/eegets/plugin/upload/${PUBLISH_VERSION}/upload-${PUBLISH_VERSION}.jar")
            artifact androidSourcesJar

            // Self-explanatory metadata for the most part
            pom {        
                //第 3 处
                name = PUBLISH_ARTIFACT_ID
                description = '自动化打包上传到蒲公英等三方平台,解放双手,方便测试人员下载' //项目描述
                // If your project has a dedicated site, use its URL here
                url = 'https://github.com/eegets/UploadApkPlugin' //项目github链接
                licenses {
                    license {
                        //协议类型,一般默认Apache License2.0的话不用改:
                        name = 'The Apache License, Version 2.0'
                        url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                developers {
                    developer {
                        //第 4 处
                        id = 'xxx' //你的sonatype用户名
                        name = 'xxx' //你的sonatype用户名
                        email = 'xxx' //你的sonatype注册邮箱
                    }
                }
                // Version control info, if you're using GitHub, follow the format as seen here
                scm {
                    //第 5 处
                    //修改成你的Git地址:
                    connection = 'scm:git@github.com:eegets/UploadApkPlugin.git'
                    developerConnection = 'scm:git@github.com:eegets/UploadApkPlugin.git'
                    //分支地址:
                    url = 'https://github.com/eegets/UploadApkPlugin/tree/master'
                }
                // A slightly hacky fix so that your POM will include any transitive dependencies
                // that your library builds upon
                withXml {
                    def dependenciesNode = asNode().appendNode('dependencies')

                    project.configurations.implementation.allDependencies.each {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                    }
                }
            }
        }
    }
    repositories {
        // The repository to publish to, Sonatype/MavenCentral
        maven {
            //第 6 处
            name = "UploadApkPlugin"
            //此处用'https://s01.oss.sonatype.org'替代'https://oss.sonatype.org',因为`https://oss.sonatype.org`会出现nexus后台无法登陆以及发布出现`Received status code 403 from server: Forbidden`问题
            def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
            def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
            // You only need this if you want to publish snapshots, otherwise just set the URL
            // to the release repo directly
            url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl

            // The username and password we've fetched earlier
            credentials {
                username ossrhUsername
                password ossrhPassword
            }
        }
    }
}
signing {
    sign publishing.publications
}

如上述代码,我们需要配置 6

第 1 处

在项目的根目录local.properties文件中增加如下配置

#//刚才获取的秘钥后8位
signing.keyId=XXXX

#//步骤4中设置的密码
signing.password=XXXX

#//生成的secring.gpg文件目录
signing.secretKeyRingFile=/Users/xxxx/xxxx/secring.gpg

#//sonatype用户名
ossrhUsername=xxxx

#//sonatype密码
ossrhPassword=xxxx

第 2 处

在要提交的module下的build.gradle文件中,添加如下代码:

注意:此处的ext{}apply from: '../publish-mavencentral.gradle'顺序一定不能乱,必须是先ext,再apply from

ext {
    PUBLISH_ARTIFACT_ID = "uploadPlugin" //你的artifact_id,一般是module的名字
    PUBLISH_VERSION = "1.0.3"  //发布版本号
    PUBLISH_GROUP_ID = 'xxx'  //你的sonatype的group_id
}
apply from: '../publish-mavencentral.gradle'

第 3 处

publish-mavencentral.gradle配置项目描述和项目GitHub地址,如下:

name = PUBLISH_ARTIFACT_ID description = '项目描述' //项目描述

url = 'https://github.com/eegets/UploadApkPlugin' //项目github链接

第 4 处

配置sonatype的信息,如下:

id = 'xxx' //你的sonatype用户名 
name = 'xxx' //你的sonatype用户名 
email = 'xxx' //你的sonatype注册邮箱

第 5 处

配置github信息,如下:


connection = 'scm:git@github.com:eegets/UploadApkPlugin.git'  //分支地址

developerConnection = 'scm:git@github.com:eegets/UploadApkPlugin.git' //分支地址: 

url = 'https://github.com/eegets/UploadApkPlugin/tree/master'

第 6 处

配置项目名称和发布地址

name = "UploadApkPlugin" 

releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" def 

snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"

注意:此处用https://s01.oss.sonatype.org 替代 https://oss.sonatype.org ,因为https://oss.sonatype.org会出现nexus后台无法登陆以及发布出现Received status code 403 from server: Forbidden问题

创建GPG秘钥

  1. www.gnupg.org/download/,从这里下载并安装GPG客户端,我的是mac,所以选择如下框中的,点击下一步安装即可。如下图

image.png

  1. 安装成功后,打开终端,在命令行中执行命令gpg --full-gen-key,注意,一定要在命令行中执行命令,不能在客户端界面做。

image.png

  1. 如上图,加密方式选择RSA and RSA,长度输入4096,过期时间直接回车不用管,然后输入一个user ID并且提供一个邮箱,我直接用的我sonatype的用户名和邮箱。最后一步输入'O',表示OK。

  2. 之后会弹出一个对话框,让输入密码。

image.png

gpg: revocation certificate stored as '~/.gnupg/openpgp-revocs.d/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXE478F7CC.rev' public and secret key created and signed.

pub rsa4096 2021-03-22 [SC] XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXEE478F7CC uid boybeak boybeak@gmail.com sub rsa4096 2021-03-22 [E] ```

这会为你在~/.gnupg/openpgp-revocs.d/目录下创建一个.rev文件,记住pub的末尾8位。

  1. 接下来创建secring.gpg文件,命令行执行gpg --export-secret-keys -o secring.gpg,这会要求你输入在步骤4中设置的密码,在你项目根目录下会出现secring.gpg文件。因我我是在当前项目目录下执行,所以secring.gpg文件生成在项目根目录下。如下图:

image.png

  1. 回到gpg客户端,选择我们刚生成的秘钥条目,右键,选择Send Public Key to Key Server。记住后边八位,如下图圈起来的八位:

image.png

做完以上gpg的配置之后我们就可以完善我们上边第 1 步了。

local.properties配置

#//刚才获取的秘钥后8位
signing.keyId=XXXX

#//步骤4中设置的密码
signing.password=XXXX

#//生成的secring.gpg文件目录
signing.secretKeyRingFile=/Users/xxxx/xxxx/secring.gpg

#//sonatype用户名
ossrhUsername=xxxx

#//sonatype密码
ossrhPassword=xxxx

执行打包和上传

设置完这些后,在AndroidStudio右侧的gradle tasks中找到你想提交的module,先后执行以下两个任务。

image.png

按照上述这么多配置之后,不出意外打包和上传都将成功[如有编译失败,请再翻翻上述文章]

上传成功后,打开Nexus Repository Manager,登录你的sonatype账号,在左侧Staging Repositories页面找到你的group id,选中,点击上边的close,等待几分钟十几分钟后刷新状态,等其状态变为closed后,再点击Release,则所有人都用使用你的库了。

备注: 最好是登陆https://s01.oss.sonatype.orghttps://oss.sonatype.org亲测无法登陆,原因请看:issues.sonatype.org/browse/OSSR…

image.png

接下来,需要等待一段时间,待Activity选项卡中出现对号的“Repository closed”即完成准备,然后点击Release按钮发布到MavenCentral,等待几个小时后可以在 search.maven.org/ 查询发布结果。

Missing: no javadoc jar found in folder解决办法

按照上述方式我们就算完成了maven的打包和发布,如果在nexus最后执行Close的时候出现Close 失败,并且报:Missing: no javadoc jar found in folder解决办法,请移步我写的另外一篇文章 Missing: no javadoc jar found in folder解决办法,关于 Missing: no javadoc jar found in folder解决办法的解决办法

注意以上几处引用的需要注意的地方,这些注意的地方可以祝你避坑!!!

源码

github.com/eegets/Uplo…

参考资料