Android Studio發(fā)布jar到Sonatype Maven Central

最近在整理一個(gè)項(xiàng)目椭赋,希望能分享給人類抚岗。折騰老半天,終于獻(xiàn)出去了:


com.github.2ndlines:download:+

謹(jǐn)此此篇記錄我踩過的坑哪怔,以及如何爬出坑宣蔚。希望對(duì)讀者有所幫助。

電腦環(huán)境:
OS: Mac OS 10.14.4
IDE:Android Studio 3.5
GPG:2.2.8

步驟一:源碼準(zhǔn)備

在Android Studio中完成項(xiàng)目開發(fā)和測試认境,盡可能的保證您貢獻(xiàn)的項(xiàng)目好用耐用件已;

步驟二:向Sonatype提交工單

坑位預(yù)警:Group Id要求唯一
工單提交地址:https://issues.sonatype.org/secure/Dashboard.jspa
這是一個(gè)JIRA平臺(tái),如果沒有賬號(hào)元暴,則注冊(cè)一個(gè)。
注冊(cè)地址:https://issues.sonatype.org/secure/Signup!default.jspa

Sign up

注冊(cè)成功之后兄猩,記下用戶名和密碼茉盏,在上傳jar到Nexus時(shí)要用到。
登錄Sonatype JIRA枢冤,并新建工單:


Create ticket

ticket.png

根據(jù)其提示填好對(duì)應(yīng)的內(nèi)容鸠姨,提交。

提交之后淹真,平臺(tái)會(huì)給你留言讶迁,還會(huì)有相應(yīng)的郵件通知。
告訴你哪里有問題或者接下來該怎么做核蘸。如圖所示:


comment_1.png

如果有信息需要修改巍糯,比如要修改Group Id啸驯,改完之后點(diǎn)擊工單上方的“response”按鈕,以通知平臺(tái)已修改完畢祟峦,平臺(tái)會(huì)再次查驗(yàn)?zāi)愕男畔ⅰ?br> 直到平臺(tái)回復(fù)以下類似內(nèi)容:


comment_success.png

至此罚斗,就可以進(jìn)行下一步,上傳jar包宅楞。

步驟三:上傳jar包

jar包通過gradle腳本上傳针姿。
在Android工程的根目錄下新建maven_push.gradle文件。
文件內(nèi)容如下:

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文件中設(shè)置POM信息距淫,實(shí)例如下:

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:git@github.com:2ndLines/XDownloadManager.git
POM_SCM_DEV_CONNECTION=scm:git@github.com: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婶希,表示上傳快照版本榕暇,否則表示上傳正式版本。
其中的私有信息請(qǐng)?zhí)鎿Q成你個(gè)人的饲趋。

配置GPG信息拐揭,用于簽署上傳的jar或aar文件

如果沒有安裝gpg,請(qǐng)先進(jìn)行安裝奕塑。

$ brew install gpg

生成密鑰對(duì)(記住簽名密碼堂污,后面要用):

$ gpg --gen-key

查看公鑰Id:

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

例如:
pub rsa2048/F7D94EDD 2019-11-08 [SC] [有效至:2021-11-07] ,
rsa2048后面的F7D94EDD就是公鑰Id。
上傳公鑰Id到公網(wǎng):

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

生成密鑰環(huán)文件:

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

如果有多套密鑰對(duì)龄砰,則可通過指定uid來導(dǎo)出指定的密鑰盟猖。例如:

$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賬號(hào)信息,也就是創(chuàng)建工單時(shí)的賬號(hào)和密碼
nexusUsername=[your_sonatype_account]
nexusPassword=[your_sonatype_password]

至此换棚,就可以通過gradle腳本上傳jar到sonatype nexus式镐。
進(jìn)入Android Studio工程,打開terminal固蚤,

$ ./gradlew uploadArchives

指令執(zhí)行成功娘汞,表示上傳成功。

步驟五:驗(yàn)證jar夕玩,提交審核

完成上一步之后你弦,登錄sonatype nexus進(jìn)行查看,登錄賬號(hào)跟創(chuàng)建工單時(shí)注冊(cè)的賬號(hào)一致燎孟。

  • 如果VERSION_NAME中包含SNAPSHOT禽作,則表示上傳的是快照版本,查看位置為:
    snapshot.png

    按groudId路徑搜索你的jar時(shí)揩页,可能需要等1分鐘左右旷偿,視網(wǎng)絡(luò)而定,切莫急躁。
  • 如果VERSION_NAME中不包含SNAPSHOT萍程,則表示上傳正式版本幢妄。查看路徑為:
    release.png

選中上傳的文件,然后點(diǎn)擊“close”按鈕尘喝,然后查看下方的activity欄磁浇,看看是否有驗(yàn)證錯(cuò)誤,如果沒有朽褪,則點(diǎn)擊“release”按鈕置吓,并到工單下留言。如果有缔赠,可到下方留言衍锚,或自行擺渡解決。
工單留言實(shí)例如下圖所示:

image.png

我在驗(yàn)證release版本時(shí)遇到的坑:

  1. failed:signature validation. 簽名驗(yàn)證失敗嗤堰,提示信息說缺失*.asc文件戴质。因?yàn)槲以谂渲胓pg信息時(shí)沒有配置signing.secretKeyRingFile 。因?yàn)槲矣玫膅pg版本高于2.1踢匣, 不會(huì)自行產(chǎn)生secring.gpg文件告匠。

    坑啊

  2. failed:POM validation. POM文件驗(yàn)證失敗。因?yàn)閙aven_push.gradle和POM配置信息是從網(wǎng)上找的离唬。剛開始找了一些缺胳膊少腿的后专。坑笆漭骸F莅ァ!

  3. 我剛把release包上傳到nexus嫂用,就跑去給Sonatype JIRA留言型凳,結(jié)果人家提示我說:


    image.png

    所以我在文章中給出的步驟是jar提交nexus,然后自行查看驗(yàn)證結(jié)果無誤之后再到JIRA留言嘱函,以免浪費(fèi)時(shí)間甘畅。

另外,至于為什么是不包含SNAPSHOT則為正式版本往弓,因?yàn)?code>maven_push.gradle腳本函數(shù)中是這么設(shè)定的橄浓。也是約定俗成的。

到工單下留言之后亮航,Sonatype JIRA會(huì)進(jìn)行最后審核,通過之后匀们,會(huì)收到類似如下留言:


comment_finish.png

愉快的等待2個(gè)小時(shí)后缴淋,到Sonatype中央庫搜索你的jar。如果能搜到,則表示已審核通過重抖,成功進(jìn)入maven中央庫露氮。恭喜你!钟沛!
以后就可以愉快地“close”和“release”了畔规。

測試你發(fā)布到中央庫的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()
    }
}
...

其實(shí),上傳jar中遇到坑都不算坑畜埋,真正的坑是jar包里的坑莫绣。哈哈哈~
最后,希望更新開發(fā)者加入開源陣營悠鞍,齊力帶飛中國的軟件開源工程对室,在開源排行榜上多一些國人的面孔和組織。加油?Ъ馈掩宜!


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市么翰,隨后出現(xiàn)的幾起案子牺汤,更是在濱河造成了極大的恐慌,老刑警劉巖硬鞍,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慧瘤,死亡現(xiàn)場離奇詭異,居然都是意外死亡固该,警方通過查閱死者的電腦和手機(jī)锅减,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伐坏,“玉大人怔匣,你說我怎么就攤上這事¤氤粒” “怎么了每瞒?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纯露。 經(jīng)常有香客問我剿骨,道長,這世上最難降的妖魔是什么埠褪? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任浓利,我火速辦了婚禮挤庇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贷掖。我一直安慰自己嫡秕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布苹威。 她就那樣靜靜地躺著昆咽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牙甫。 梳的紋絲不亂的頭發(fā)上掷酗,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音腹暖,去河邊找鬼汇在。 笑死,一個(gè)胖子當(dāng)著我的面吹牛脏答,可吹牛的內(nèi)容都是我干的糕殉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼殖告,長吁一口氣:“原來是場噩夢啊……” “哼阿蝶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起黄绩,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤羡洁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后爽丹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筑煮,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年粤蝎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了真仲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡初澎,死狀恐怖秸应,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情碑宴,我是刑警寧澤软啼,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站延柠,受9級(jí)特大地震影響祸挪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贞间,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一贿条、第九天 我趴在偏房一處隱蔽的房頂上張望盈罐。 院中可真熱鬧,春花似錦闪唆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至础浮,卻和暖如春帆调,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背豆同。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工番刊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人影锈。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓芹务,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸭廷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子枣抱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容