Android Studio发布jar到Sonatype Maven Central

最近在整理一个项目,希望能分享给人类。折腾老半天,终于献出去了:


com.github.2ndlines:download:+

谨此此篇记录我踩过的坑,以及如何爬出坑。希望对读者有所帮助。

电脑环境:
OS: Mac OS 10.14.4
IDE:Android Studio 3.5
GPG:2.2.8

步骤一:源码准备

在Android Studio中完成项目开发和测试,尽可能的保证您贡献的项目好用耐用;

步骤二:向Sonatype提交工单

坑位预警:Group Id要求唯一
工单提交地址:https://issues.sonatype.org/secure/Dashboard.jspa
这是一个JIRA平台,如果没有账号,则注册一个。
注册地址:https://issues.sonatype.org/secure/Signup!default.jspa

Sign up

注册成功之后,记下用户名和密码,在上传jar到Nexus时要用到。
登录Sonatype JIRA,并新建工单:


Create ticket

ticket.png

根据其提示填好对应的内容,提交。

提交之后,平台会给你留言,还会有相应的邮件通知。
告诉你哪里有问题或者接下来该怎么做。如图所示:


comment_1.png

如果有信息需要修改,比如要修改Group Id,改完之后点击工单上方的“response”按钮,以通知平台已修改完毕,平台会再次查验你的信息。
直到平台回复以下类似内容:


comment_success.png

至此,就可以进行下一步,上传jar包。

步骤三:上传jar包

jar包通过gradle脚本上传。
在Android工程的根目录下新建maven_push.gradle文件。
文件内容如下:

apply plugin: 'maven'
apply plugin: 'signing'

def sonatypeRepositoryUrl

def isReleaseBuild() {
    return VERSION_NAME.contains("SNAPSHOT") == false
}
if (isReleaseBuild()) {
    println 'RELEASE BUILD'
    sonatypeRepositoryUrl = hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
            : "https://oss.sonatype.org/service/local/staging/deploy/maven2"
} else {
    println 'DEBUG BUILD'
    sonatypeRepositoryUrl = hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
            : "https://oss.sonatype.org/content/repositories/snapshots"
}

def getRepositoryUsername() {
    return hasProperty('nexusUsername') ? nexusUsername : ""
}

def getRepositoryPassword() {
    return hasProperty('nexusPassword') ? nexusPassword : ""
}

afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
                pom.groudId = GROUP_ID
                pom.artifactId = POM_ARTIFACT_ID
                pom.version = VERSION_NAME

                repository(url: sonatypeRepositoryUrl) {
                    authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
                }

                pom.project {
                    name POM_NAME
                    packaging POM_PACKAGING
                    description POM_DESCRIPTION
                    url POM_URL

                    scm {
                        url POM_SCM_URL
                        connection POM_SCM_CONNECTION
                        developerConnection POM_SCM_DEV_CONNECTION
                    }

                    licenses {
                        license {
                            name POM_LICENCE_NAME
                            url POM_LICENCE_URL
                            distribution POM_LICENCE_DIST
                        }
                    }

                    developers {
                        developer {
                            id POM_DEVELOPER_ID
                            name POM_DEVELOPER_NAME
                        }
                    }
                }
            }
        }
    }

    signing {
        required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
        println 'Signing archives...'
        sign configurations.archives
    }

    task androidJavadocs(type: Javadoc) {
        source = android.sourceSets.main.java.sourceFiles
        options {
            links "http://docs.oracle.com/javase/7/docs/api/"
            linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
        }
        classpath += project.android.libraryVariants.toList().first().javaCompile.classpath
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    }

    task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
        classifier = 'javadoc'
        from androidJavadocs.destinationDir
    }

    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.sourceFiles
    }

    artifacts {
        archives androidSourcesJar
        archives androidJavadocsJar
    }
}

然后引用maven_push.gradle。
在library module的build.gradle文件的头部或尾部添加:

apply from: '../maven_push.gradle'
步骤四:配置maven信息:

在根目录的的gradle.properties文件中设置POM信息,实例如下:

VERSION_NAME=1.0.2
VERSION_CODE=2
GROUP_ID=com.github.2ndlines 

POM_DESCRIPTION=Android Download Library
POM_URL=https://github.com/2ndLines/XDownloadManager
POM_SCM_URL=https://github.com/2ndLines/XDownloadManager
POM_SCM_CONNECTION=scm:[email protected]:2ndLines/XDownloadManager.git
POM_SCM_DEV_CONNECTION=scm:[email protected]:2ndLines/XDownloadManager.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=Apache 2.0
POM_DEVELOPER_ID=[your id]
POM_DEVELOPER_NAME=[your name]

POM_NAME=Download library
POM_ARTIFACT_ID=download
POM_PACKAGING=aar
WEB_SITE_URL=https://github.com/2ndLines/XDownloadManager
ISSUE_TRACKER_URL=https://github.com/2ndLines/XDownloadManager/issues
VCS_URL=https://github.com/2ndLines/XDownloadManager.git

RELEASE_REPOSITORY_URL=https://oss.sonatype.org/service/local/staging/deploy/maven2
SNAPSHOT_REPOSITORY_URL=https://oss.sonatype.org/content/repositories/snapshots

配置信息中的VERSION_NAME如果包含SNAPSHOT,如1.0.2-SNAPSHOT,表示上传快照版本,否则表示上传正式版本。
其中的私有信息请替换成你个人的。

配置GPG信息,用于签署上传的jar或aar文件

如果没有安装gpg,请先进行安装。

$ brew install gpg

生成密钥对(记住签名密码,后面要用):

$ gpg --gen-key

查看公钥Id:

$ gpg --list-key --keyid-format short

例如:
pub rsa2048/F7D94EDD 2019-11-08 [SC] [有效至:2021-11-07] ,
rsa2048后面的F7D94EDD就是公钥Id。
上传公钥Id到公网:

gpg --keyserver hkp://pgp.mit.edu --send-keys  [your_pubkey_id]

生成密钥环文件:

$gpg --export-secret-keys  -o ~/.gnupg/secring.gpg

如果有多套密钥对,则可通过指定uid来导出指定的密钥。例如:

$gpg --export-secret-keys  -o ~/.gnupg/secring.gpg  [your_email@your_domain.com]

配置gpg信息:

##gpg信息
signing.keyId=[your_pubkey_id]
signing.password=[your_signing_password]
signing.secretKeyRingFile=/Users/[your_username]/.gnupg/secring.gpg
##nexus账号信息,也就是创建工单时的账号和密码
nexusUsername=[your_sonatype_account]
nexusPassword=[your_sonatype_password]

至此,就可以通过gradle脚本上传jar到sonatype nexus。
进入Android Studio工程,打开terminal,

$ ./gradlew uploadArchives

指令执行成功,表示上传成功。

步骤五:验证jar,提交审核

完成上一步之后,登录sonatype nexus进行查看,登录账号跟创建工单时注册的账号一致。

  • 如果VERSION_NAME中包含SNAPSHOT,则表示上传的是快照版本,查看位置为:
    snapshot.png

    按groudId路径搜索你的jar时,可能需要等1分钟左右,视网络而定,切莫急躁。
  • 如果VERSION_NAME中不包含SNAPSHOT,则表示上传正式版本。查看路径为:
    release.png

选中上传的文件,然后点击“close”按钮,然后查看下方的activity栏,看看是否有验证错误,如果没有,则点击“release”按钮,并到工单下留言。如果有,可到下方留言,或自行摆渡解决。
工单留言实例如下图所示:

image.png

我在验证release版本时遇到的坑:

  1. failed:signature validation. 签名验证失败,提示信息说缺失*.asc文件。因为我在配置gpg信息时没有配置signing.secretKeyRingFile 。因为我用的gpg版本高于2.1, 不会自行产生secring.gpg文件。

    坑啊

  2. failed:POM validation. POM文件验证失败。因为maven_push.gradle和POM配置信息是从网上找的。刚开始找了一些缺胳膊少腿的。坑啊!!

  3. 我刚把release包上传到nexus,就跑去给Sonatype JIRA留言,结果人家提示我说:


    image.png

    所以我在文章中给出的步骤是jar提交nexus,然后自行查看验证结果无误之后再到JIRA留言,以免浪费时间。

另外,至于为什么是不包含SNAPSHOT则为正式版本,因为maven_push.gradle脚本函数中是这么设定的。也是约定俗成的。

到工单下留言之后,Sonatype JIRA会进行最后审核,通过之后,会收到类似如下留言:


comment_finish.png

愉快的等待2个小时后,到Sonatype中央库搜索你的jar。如果能搜到,则表示已审核通过,成功进入maven中央库。恭喜你!!
以后就可以愉快地“close”和“release”了。

测试你发布到中央库的jar

在module的build.gradle中添加库依赖,例如:

...
dependencies {
    //your other dependencies
    implementation 'com.github.2ndlines:download:1.0.3-SNAPSHOT'
}
...
  • 如果是快照版本,在根build.gradle中添加maven库快照地址:
...
allprojects {
    repositories {
        ...
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots'}
    }
}
...
  • 如果是正式版本,则在根build.gradle中添加maven库地址:
...
allprojects {
    repositories {
        ...
        mavenCentral()
    }
}
...

其实,上传jar中遇到坑都不算坑,真正的坑是jar包里的坑。哈哈哈~
最后,希望更新开发者加入开源阵营,齐力带飞中国的软件开源工程,在开源排行榜上多一些国人的面孔和组织。加油!!


你可能感兴趣的:(Android Studio发布jar到Sonatype Maven Central)