如何發(fā)布Android庫(kù)到Maven中心倉(cāng)庫(kù)

前言

本文用于記錄如何將自己的庫(kù)上傳到maven中心倉(cāng)庫(kù),

  • 首先我們需要注冊(cè)sonatype的jira賬號(hào)装蓬,然后申請(qǐng)創(chuàng)建自己的repo蹈丸,等待官方審核通過(guò)之后即可擁有自己的空間壁涎;
  • 我們使用gradle的maven-publish和signing插件來(lái)簡(jiǎn)化打包上傳的操作坏瘩,通過(guò)配置之后,即可通過(guò)gradle任務(wù)來(lái)上傳到maven倉(cāng)庫(kù)润脸;
  • 上傳時(shí)可以選擇上傳到snapshot存儲(chǔ)區(qū)或者staging存儲(chǔ)區(qū)柬脸,這兩個(gè)存儲(chǔ)去上傳之后即可立刻訪問(wèn),snapshot區(qū)可公開(kāi)訪問(wèn)毙驯,而staging只能供自己或有權(quán)限的人使用倒堕,需要驗(yàn)證用戶名密碼;
  • 如需要將staging區(qū)的版本公開(kāi)給所有人使用爆价,可通過(guò)sonatype網(wǎng)站上的release操作來(lái)公開(kāi)垦巴;

創(chuàng)建sonatype賬號(hào)及group

參考: OSSRH Guide - The Central Repository Documentation (sonatype.org)

  1. 創(chuàng)建Jira賬號(hào)

  2. 創(chuàng)建issues: 創(chuàng)建問(wèn)題 - Sonatype JIRA

創(chuàng)建issues并且經(jīng)管理員同意后媳搪,才可以上傳倉(cāng)庫(kù),創(chuàng)建之后相當(dāng)于擁有了一個(gè)group骤宣,之后可以往這個(gè)group上傳其他的項(xiàng)目而無(wú)需再次建立issues秦爆;

image-20210525091621597

新建issues之后,系統(tǒng)會(huì)回復(fù)憔披,根據(jù)回復(fù)的要求進(jìn)行處理即可等限,通過(guò)后會(huì)有類似的回復(fù):

com.github.hanlyjiang has been prepared, now user(s) hanlyjiang can:
Deploy snapshot artifacts into repository https://oss.sonatype.org/content/repositories/snapshots
Deploy release artifacts into the staging repository https://oss.sonatype.org/service/local/staging/deploy/maven2
Release staged artifacts into repository 'Releases'
please comment on this ticket when you promoted your first release, thanks

即表明我們擁有了自己的group;

生成簽名key

所有上傳到倉(cāng)庫(kù)中的文件必須進(jìn)行簽名芬膝,否則會(huì)無(wú)法發(fā)布望门,所以我們需要生成簽名用的key,同時(shí)還需要將key推送到公共的key服務(wù)器锰霜,然sonatype服務(wù)器可以訪問(wèn)到筹误,以進(jìn)行驗(yàn)證;

生成key

過(guò)程中需要輸入密碼癣缅,==輸入后請(qǐng)記住密碼==

gpg --gen-key
gpg (GnuPG) 2.2.22; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: 鑰匙箱‘/Users/hanlyjiang/.gnupg/pubring.kbx’已創(chuàng)建
注意:使用 “gpg --full-generate-key” 以獲得一個(gè)功能完整的密鑰產(chǎn)生對(duì)話框厨剪。

GnuPG 需要構(gòu)建用戶標(biāo)識(shí)以辨認(rèn)您的密鑰。

真實(shí)姓名: hanlyjiang
電子郵件地址: hanlyjiang@outlook.com
您選定了此用戶標(biāo)識(shí):
    “hanlyjiang <hanlyjiang@outlook.com>”

更改姓名(N)所灸、注釋(C)丽惶、電子郵件地址(E)或確定(O)/退出(Q)炫七? o
我們需要生成大量的隨機(jī)字節(jié)爬立。在質(zhì)數(shù)生成期間做些其他操作(敲打鍵盤(pán)
、移動(dòng)鼠標(biāo)万哪、讀寫(xiě)硬盤(pán)之類的)將會(huì)是一個(gè)不錯(cuò)的主意侠驯;這會(huì)讓隨機(jī)數(shù)
發(fā)生器有更好的機(jī)會(huì)獲得足夠的熵。
我們需要生成大量的隨機(jī)字節(jié)奕巍。在質(zhì)數(shù)生成期間做些其他操作(敲打鍵盤(pán)
吟策、移動(dòng)鼠標(biāo)、讀寫(xiě)硬盤(pán)之類的)將會(huì)是一個(gè)不錯(cuò)的主意的止;這會(huì)讓隨機(jī)數(shù)
發(fā)生器有更好的機(jī)會(huì)獲得足夠的熵檩坚。
gpg: 密鑰 E8A99FE282B70849 被標(biāo)記為絕對(duì)信任
gpg: 吊銷證書(shū)已被存儲(chǔ)為‘/Users/hanlyjiang/.gnupg/openpgp-revocs.d/0B372361CC1A9AE2452D43FDE8A99FE282B70849.rev’
公鑰和私鑰已經(jīng)生成并被簽名。

pub   rsa3072 2021-05-24 [SC] [有效至:2023-05-24]
      0B372361CC1A9AE2452D43FDE8A99FE282B70849
uid                      hanlyjiang <hanlyjiang@outlook.com>
sub   rsa3072 2021-05-24 [E] [有效至:2023-05-24]

列出key

gpg --list-keys
gpg: 正在檢查信任度數(shù)據(jù)庫(kù)
gpg: 絕對(duì)信任密鑰 8F5EC255E5A0D063 的公鑰未找到
gpg: 絕對(duì)信任密鑰 4150E419D483B9A6 的公鑰未找到
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深度:0  有效性:  3  已簽名:  0  信任度:0-诅福,0q匾委,0n,0m氓润,0f赂乐,3u
gpg: 下次信任度數(shù)據(jù)庫(kù)檢查將于 2023-05-24 進(jìn)行
/Users/hanlyjiang/.gnupg/pubring.kbx
------------------------------------
pub   rsa3072 2021-05-24 [SC] [有效至:2023-05-24]
      0B372361CC1A9AE2452D43FDE8A99FE282B70849
uid           [ 絕對(duì) ] hanlyjiang <hanlyjiang@outlook.com>
sub   rsa3072 2021-05-24 [E] [有效至:2023-05-24]

發(fā)送key到服務(wù)器

提示:

如果一個(gè)key服務(wù)器不通的話,可以換一個(gè)重新來(lái)一遍咖气,只要上傳成功一個(gè)即可挨措。

key需要發(fā)送到服務(wù)器上挖滤,以便sonatype獲取并校驗(yàn)簽名,通過(guò)如下命令上傳:

設(shè)置key的信息:

KEY_SERVER=hkp://pool.sks-keyservers.net
KEY_ID=0B372361CC1A9AE2452D43FDE8A99FE282B70849

上傳:

$ gpg --keyserver $KEY_SERVER --send-keys $KEY_ID
gpg: 正在發(fā)送密鑰 E8A99FE282B70849 到 hkp://pool.sks-keyservers.net

查看是否成功:

KEY_SERVER=hkp://pool.sks-keyservers.net
gpg --keyserver $KEY_SERVER --recv-keys $KEY_ID

可用的key-server:

hkp://keyserver.ubuntu.com
hkp://pool.sks-keyservers.net
hkp://keys.openpgp.org
hkp://keys.gnupg.net
hkp://keys.openpgp.org

導(dǎo)出key

導(dǎo)出公鑰:

gpg -a -o ~/.gnupg/maven-pub.key --export $KEY_ID

導(dǎo)出私鑰:(需要輸入密碼)

gpg -a -o ~/.gnupg/maven-prv.key --export-secret-keys $KEY_ID

導(dǎo)出gpgkey:

gpg --keyring secring.gpg --export-secret-keys > ~/.gnupg/secring.gpg

gradle配置

官方關(guān)于Gradle下上傳的說(shuō)明在這里 Gradle - The Central Repository Documentation (sonatype.org)浅役,這個(gè)文章中使用的是maven插件斩松,另外還有一個(gè)maven-publish插件,我們使用maven-publish這個(gè)插件觉既;

gradle.properties

修改gradle配置:

#  ~/.gradle/gradle.properties 寫(xiě)入如下內(nèi)容:

ossrhUsername=hanlyjiang # jira的用戶名
ossrhPassword=#jira的密碼

# 公鑰ID的后8位 0B372361CC1A9AE2452D43FDE8A99FE282B70849
signing.keyId=82B70849
signing.password=生成key時(shí)的密碼
signing.secretKeyRingFile=/Users/hanlyjiang/.gnupg/secring.gpg

用戶名和密碼可以隨意命名砸民,只要自己在build.gradle對(duì)應(yīng)上就可以

而 signing 的配置則需要保持名稱一致。

build.gradle:

參考:

我們?cè)谛枰蟼鞯捻?xiàng)目中配置,注意pom中的信息也需要補(bǔ)全尝艘,否則上傳之后無(wú)法通過(guò)sonatype的檢查演侯,無(wú)法發(fā)布;

??注意: 有的人的上傳地址可能是 https://s01.oss.sonatype.org 的域名背亥,如:

  • https://s01.oss.sonatype.org/content/repositories/snapshots
    
  • https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
    
plugins {
    id 'com.android.library'
    id 'signing'
    id 'maven-publish'
}

def VERSION="1.0.1"
android {
    defaultConfig {
        minSdkVersion 22
        targetSdkVersion 30
        versionCode 1
        versionName VERSION
    }
}


// Because the components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.
afterEvaluate {
    publishing {
        repositories {
            maven {
                name "local"
                // change to point to your repo, e.g. http://my.org/repo
                url = "$buildDir/repo"
            }
            maven {
                name "sonartype-Staging"
                // change to point to your repo, e.g. http://my.org/repo
                url = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
              //  https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
                credentials {
                    username = ossrhUsername
                    password = ossrhPassword
                }
            }
            // 定義snapshot倉(cāng)庫(kù)
            maven {
                name "sonatype-Snapshots"
                // change to point to your repo, e.g. http://my.org/repo
                url = "https://oss.sonatype.org/content/repositories/snapshots/"
                credentials {
                    username = ossrhUsername
                    password = ossrhPassword
                }
            }
        }
        publications {
            // Creates a Maven publication called "release".
            release(MavenPublication) {
                // Applies the component for the release build variant.
                from components.release

                // You can then customize attributes of the publication as shown below.
                groupId = 'com.github.hanlyjiang'
                artifactId = 'apf_library'
                version = VERSION
                pom {
                    name = 'HJ Android Plugin Framework'
                    description = 'A Android Plugin Framework'
                    url = 'https://github.com/hanlyjiang/apf-library'
                    licenses {
                        license {
                            name='The Apache Software License, Version 2.0'
                            url='http://www.apache.org/licenses/LICENSE-2.0.txt'
                        }
                    }
                    developers {
                        developer {
                            id = 'hanlyjiang'
                            name = 'hanly jiang'
                            email = 'hanlyjiang@outlook.com'
                        }
                    }
                    scm {
                        connection = 'https://github.com/hanlyjiang/apf-library'
                        developerConnection = 'https://github.com/hanlyjiang/apf-library.git'
                        url = 'https://github.com/hanlyjiang/apf-library'
                    }
                }
            }
            // Creates a Maven publication called “debug”.
            debug(MavenPublication) {
                // Applies the component for the debug build variant.
                from components.debug

                groupId = 'com.github.hanlyjiang'
                artifactId = 'apf_library-debug'
                version = String.format("%s-SNAPSHOT",VERSION)

                pom {
                    name = 'HJ Android Plugin Framework'
                    description = 'A Android Plugin Framework'
                    url = 'https://github.com/hanlyjiang/apf-library'
                    licenses {
                        license {
                            name='The Apache Software License, Version 2.0'
                            url='http://www.apache.org/licenses/LICENSE-2.0.txt'
                        }
                    }
                    developers {
                        developer {
                            id = 'hanlyjiang'
                            name = 'hanly jiang'
                            email = 'hanlyjiang@outlook.com'
                        }
                    }
                    scm {
                        connection = 'https://github.com/hanlyjiang/apf-library'
                        developerConnection = 'https://github.com/hanlyjiang/apf-library.git'
                        url = 'https://github.com/hanlyjiang/apf-library'
                    }
                }
            }
        }

        signing {
            sign publishing.publications.release , publishing.publications.debug
        }
    }
}

發(fā)布腳本配置中有以下需要注意:

  • groupId:需要配置自己申請(qǐng)的 groupId秒际;
  • artifactId:需要修改為自己項(xiàng)目的 artifactId;
  • pom 中的文件描述需要修改為自己項(xiàng)目的描述狡汉;
  • repositories 部分配置了遠(yuǎn)程倉(cāng)庫(kù)對(duì)應(yīng)的用戶名和密碼娄徊,發(fā)布地址需要根據(jù)是否是新項(xiàng)目進(jìn)行修改,舊項(xiàng)目域名是 oss.sonatype.org盾戴,新項(xiàng)目域名是:s01.oss.sonatype.org
  • signing 簽名部分需要配置對(duì)應(yīng)的 gpg 密鑰和賬戶信息

關(guān)于maven 倉(cāng)庫(kù)的注意點(diǎn):

  1. snapshots倉(cāng)庫(kù)上傳的庫(kù)寄锐,其版本號(hào)需要以 -SNAPSHOT 結(jié)尾,否則可能出現(xiàn)400錯(cuò)誤尖啡;

執(zhí)行上傳任務(wù)

執(zhí)行g(shù)radle 對(duì)應(yīng)的任務(wù)即可上傳

$ module=apf-library; ./gradlew "$module":publishReleasePublicationToCenterRepository

具體生成的任務(wù)可以在AndroidStudio 的Gradle工具窗口中查看publishing分組的任務(wù)橄仆;或者通過(guò)如下命令查看

$ module=apf-library; ./gradlew "$module":tasks| grep -E "publish|generate"

generateMetadataFileForDebugPublication - Generates the Gradle metadata file for publication 'debug'.
generateMetadataFileForReleasePublication - Generates the Gradle metadata file for publication 'release'.
generatePomFileForDebugPublication - Generates the Maven POM file for publication 'debug'.
generatePomFileForReleasePublication - Generates the Maven POM file for publication 'release'.
publish - Publishes all publications produced by this project.
publishAllPublicationsToCenterRepository - Publishes all Maven publications produced by this project to the center repository.
publishAllPublicationsToLocalRepository - Publishes all Maven publications produced by this project to the local repository.
publishDebugPublicationToCenterRepository - Publishes Maven publication 'debug' to Maven repository 'center'.
publishDebugPublicationToLocalRepository - Publishes Maven publication 'debug' to Maven repository 'local'.
publishDebugPublicationToMavenLocal - Publishes Maven publication 'debug' to the local Maven repository.
publishReleasePublicationToCenterRepository - Publishes Maven publication 'release' to Maven repository 'center'.
publishReleasePublicationToLocalRepository - Publishes Maven publication 'release' to Maven repository 'local'.
publishReleasePublicationToMavenLocal - Publishes Maven publication 'release' to the local Maven repository.
publishToMavenLocal - Publishes all Maven publications produced by this project to the local Maven cache.

發(fā)布

  • close
  • release

參考:

首先需要解釋下這里的發(fā)布指的什么意思:我們的倉(cāng)庫(kù)上傳之后,實(shí)際上是存儲(chǔ)與一個(gè)臨時(shí)的獨(dú)立與公有倉(cāng)庫(kù)的地方衅斩,這個(gè)只能我們自己訪問(wèn)盆顾,如果需要將倉(cāng)庫(kù)提供給其他人訪問(wèn),就需要發(fā)布畏梆;發(fā)布的過(guò)程可以手動(dòng)在web頁(yè)面上操作您宪,也可以通過(guò)命令行來(lái)進(jìn)行;

發(fā)布需要取sonatype的網(wǎng)站上操作奠涌,以下為操作步驟:

  • 打開(kāi) Nexus Repository Manager (sonatype.org)

  • 然后登錄宪巨,登錄之后可以看到 Build Promotion 的菜單,然后打開(kāi)Staging Repository铣猩,其中會(huì)顯示已經(jīng)上傳的倉(cāng)庫(kù):

    image-20210524172822831
  • 選中一個(gè)staging repo揖铜,然后點(diǎn)擊 Close,并進(jìn)行確認(rèn)

    image-20210524172941960
  • 結(jié)果可以在Activity中查看

    image-20210524173140850

    上面的錯(cuò)誤是找不到key达皿,我們重新將key上傳到ubuntu:

gpg --keyserver $KEY_SERVER --send-keys 0B372361CC1A9AE2452D43FDE8A99FE282B70849
gpg --keyserver $KEY_SERVER --recv-keys 0B372361CC1A9AE2452D43FDE8A99FE282B70849
然后再次close
image-20210524173522647
  • 然后再進(jìn)行release

    image-20210524173756512
  • 完成后天吓,會(huì)發(fā)一個(gè)郵件通知贿肩,然后會(huì)更新jira上創(chuàng)建項(xiàng)目的issues:

    image-20210524181450169

引入并使用

引入snapshot或staging版本

可通過(guò)如下路徑確認(rèn)自己的庫(kù)是否上傳成功(注意將后面的路徑替換為自己的):

snapshot和staging的倉(cāng)庫(kù)中的版本可在推送后立即訪問(wèn),不過(guò)只能自己訪問(wèn)龄寞,需要驗(yàn)證用戶名和密碼汰规。

添加以下repo配置:

allprojects {
    repositories {
        maven {
            name = "Sonatype-Snapshots"
            setUrl("https://oss.sonatype.org/content/repositories/snapshots")
//            setUrl("https://s01.oss.sonatype.org/content/repositories/snapshots")
            credentials(PasswordCredentials::class.java) {
                username = property("ossrhUsername").toString()
                password = property("ossrhPassword").toString()
            }
        }
        maven {
            name = "Sonatype-Staging"
            setUrl("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
//            setUrl("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
            credentials(PasswordCredentials::class.java) {
                username = property("ossrhUsername").toString()
                password = property("ossrhPassword").toString()
            }
        }
        google()
        jcenter()
        mavenCentral()
    }
}

引入release版本

如果需要公開(kāi)發(fā)布給自己或其他人使用,則需要release物邑,release操作之后距離可以訪問(wèn)到有一定的時(shí)間周期溜哮,下面是一次release后收到的官方的郵件:

Central sync is activated for com.github.hanlyjiang. After you successfully release, your component will be published to Central https://repo1.maven.org/maven2/, typically within 10 minutes, though updates to https://search.maven.org can take up to two hours.

也就是說(shuō)從maven中心倉(cāng)庫(kù)中查詢需要10分鐘左右,從網(wǎng)頁(yè)搜索則需要2個(gè)小時(shí)色解,可以訪問(wèn):https://search.maven.org 來(lái)搜索茂嗓,可以通過(guò)訪問(wèn) https://repo1.maven.org/maven2/ 來(lái)確認(rèn)是否被索引了,如果被索引科阎,則可以引入到項(xiàng)目之中述吸;

在gradle中使用則只需要導(dǎo)入mavenCenter() 即可;

rootProject build.gradle:

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

app build.gradle:

implementation("com.github.hanlyjiang:apf_library:1.0")

kotlin中使用

配置

import org.gradle.api.publish.maven.MavenPom

plugins {
    id("com.android.library")
    id("signing")
    `maven-publish`
//    kotlin("android")
//    kotlin("android.extensions")
}

android {
    // 省略android配置
}

fun getMyPom(): Action<in MavenPom> {
    return Action<MavenPom> {
        name.set("Android Common Utils Lib")
        description.set("Android Common Utils Library For HJ")
        url.set("https://github.com/hanlyjiang/lib_common_utils")
        properties.set(mapOf(
                "myProp" to "value",
                "prop.with.dots" to "anotherValue"
        ))
        licenses {
            license {
                name.set("The Apache License, Version 2.0")
                url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
            }
        }
        developers {
            developer {
                id.set("hanlyjiang")
                name.set("Hanly Jiang")
                email.set("hanlyjiang@outlook.com")
            }
        }
        scm {
            connection.set("scm:git:git://github.com/hanlyjiang/lib_common_utils.git")
            developerConnection.set("scm:git:ssh://github.com/hanlyjiang/lib_common_utils.git")
            url.set("https://github.com/hanlyjiang/lib_common_utils")
        }
    }
}

afterEvaluate {
    publishing {
        publications {
            create<MavenPublication>("release") {
                from(components.getByName("release"))
                groupId = "com.github.hanlyjiang"
                artifactId = "android_common_utils"
                version = android.defaultConfig.versionName
                pom(getMyPom())
            }
        }

        repositories {
            val ossrhCredentials = Action<PasswordCredentials> {
                username = properties["ossrhUsername"].toString()
                password = properties["ossrhPassword"].toString()
            }
            // sonar的倉(cāng)庫(kù)锣笨,地址根據(jù)項(xiàng)目的版本號(hào)來(lái)確定是snapshot還是正式倉(cāng)庫(kù)
            maven {
                name = "Sonartype"

                val releasesRepoUrl = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
                val snapshotsRepoUrl = uri("https://oss.sonatype.org/content/repositories/snapshots/")
                url = if (android.defaultConfig.versionName.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
                credentials(ossrhCredentials)
                // snapshot的地址:
                // https://oss.sonatype.org/content/repositories/snapshots/com/github/hanlyjiang/android_common_utils/
            }
            // 項(xiàng)目本地的倉(cāng)庫(kù)
            maven {
                name = "ProjectLocal"

                val releasesRepoUrl = uri(layout.buildDirectory.dir("repos/releases"))
                val snapshotsRepoUrl = uri(layout.buildDirectory.dir("repos/snapshots"))
                url = if (android.defaultConfig.versionName.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
            }
        }
    }
    // https://stackoverflow.com/questions/54654376/why-is-publishing-function-not-being-found-in-my-custom-gradle-kts-file-within

    signing {
        sign(publishing.publications.getByName("release"))
    }

}

問(wèn)題:

A problem occurred configuring project ':lib_common_utils'.
> SoftwareComponentInternal with name 'java' not found.

maven plugin - Why is 'publishing' function not being found in my custom gradle.kts file within buildSrc directory? - Stack Overflow

Maven Publish Plugin (gradle.org)

上傳javadoc和source

添加javadoc和jarsource的任務(wù)

tasks.register("javadoc", Javadoc::class.java) {
    group = "publishing"
    dependsOn("assemble")
    source = android.sourceSets["main"].java.getSourceFiles()
    classpath += project.files(android.bootClasspath + File.pathSeparator)
    if (JavaVersion.current().isJava9Compatible) {
        (options as StandardJavadocDocletOptions).addBooleanOption("html5", true)
    }
    android.libraryVariants.forEach { libraryVariant ->
        classpath += libraryVariant.javaCompileProvider.get().classpath
    }
    options.apply {
        encoding("UTF-8")
        charset("UTF-8")
        isFailOnError = false

        (this as StandardJavadocDocletOptions).apply {
            addStringOption("Xdoclint:none")
            links?.add("https://developer.android.google.cn/reference/")
            links?.add("http://docs.oracle.com/javase/8/docs/api/")
        }
    }
}

tasks.register("jarSource", Jar::class.java) {
    group = "publishing"
    from(android.sourceSets["main"].java.srcDirs)
    archiveClassifier.set("sources")
}

tasks.register("jarJavadoc", Jar::class.java) {
    group = "publishing"
    dependsOn("javadoc")
    val javadoc: Javadoc = tasks.getByName("javadoc") as Javadoc
    from(javadoc.destinationDir)
    archiveClassifier.set("javadoc")
}

publish中使用

afterEvaluate {
    publishing {
        publications {
            create<MavenPublication>("release") {
                from(components.getByName("release"))
                groupId = "com.github.hanlyjiang"
                artifactId = "android_common_utils"
                version = android.defaultConfig.versionName
                pom(getMyPom())
                // 添加javadoc
                artifact(tasks.getByName("jarJavadoc") as Jar)
                // 添加source
                 artifact(tasks.getByName("jarSource") as Jar)
            }
        }

        repositories {
            val ossrhCredentials = Action<PasswordCredentials> {
                username = properties["ossrhUsername"].toString()
                password = properties["ossrhPassword"].toString()
            }
            // sonar的倉(cāng)庫(kù)蝌矛,地址根據(jù)項(xiàng)目的版本號(hào)來(lái)確定是snapshot還是正式倉(cāng)庫(kù)
            maven {
                name = "Sonartype"

                val releasesRepoUrl = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
                val snapshotsRepoUrl = uri("https://oss.sonatype.org/content/repositories/snapshots/")
                url = if (android.defaultConfig.versionName.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
                credentials(ossrhCredentials)
                // snapshot的地址:
                // https://oss.sonatype.org/content/repositories/snapshots/com/github/hanlyjiang/android_common_utils/
            }
            // 項(xiàng)目本地的倉(cāng)庫(kù)
            maven {
                name = "ProjectLocal"

                val releasesRepoUrl = uri(layout.buildDirectory.dir("repos/releases"))
                val snapshotsRepoUrl = uri(layout.buildDirectory.dir("repos/snapshots"))
                url = if (android.defaultConfig.versionName.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
            }
        }
    }
    // https://stackoverflow.com/questions/54654376/why-is-publishing-function-not-being-found-in-my-custom-gradle-kts-file-within


    signing {
        sign(publishing.publications.getByName("release"))
    }

}

? 錯(cuò)誤記錄

400 錯(cuò)誤

maven publish Received status code 400 from server

可能的原因: maven 倉(cāng)庫(kù)分兩個(gè),一個(gè)是snapshot倉(cāng)庫(kù)错英,一個(gè)是release 倉(cāng)庫(kù)入撒,如果將snapshot版本(版本號(hào)帶SNAPSHOT)的包上傳到Release倉(cāng)庫(kù)的地址,則會(huì)報(bào)錯(cuò)椭岩。

參考文章

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末氮唯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子姨伟,更是在濱河造成了極大的恐慌,老刑警劉巖豆励,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夺荒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡良蒸,警方通過(guò)查閱死者的電腦和手機(jī)技扼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)嫩痰,“玉大人剿吻,你說(shuō)我怎么就攤上這事〈模” “怎么了丽旅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵椰棘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我榄笙,道長(zhǎng)邪狞,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任茅撞,我火速辦了婚禮帆卓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘米丘。我一直安慰自己剑令,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布拄查。 她就那樣靜靜地躺著尚洽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪靶累。 梳的紋絲不亂的頭發(fā)上腺毫,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音挣柬,去河邊找鬼潮酒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邪蛔,可吹牛的內(nèi)容都是我干的急黎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼侧到,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼勃教!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起匠抗,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤故源,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后汞贸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绳军,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年矢腻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了门驾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡多柑,死狀恐怖奶是,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤聂沙,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布秆麸,位于F島的核電站,受9級(jí)特大地震影響逐纬,放射性物質(zhì)發(fā)生泄漏蛔屹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一豁生、第九天 我趴在偏房一處隱蔽的房頂上張望兔毒。 院中可真熱鬧,春花似錦甸箱、人聲如沸育叁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)豪嗽。三九已至,卻和暖如春豌骏,著一層夾襖步出監(jiān)牢的瞬間龟梦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工窃躲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留计贰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓蒂窒,卻偏偏與公主長(zhǎng)得像躁倒,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洒琢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

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