最近完成的一個(gè)小的任務(wù)是將Andorid的SDK發(fā)布到公司的maven倉(cāng)庫(kù),供內(nèi)部開(kāi)發(fā)人員使用,這里記錄一下完成這一小的任務(wù)學(xué)習(xí)的知識(shí)以及踩的坑。
使用gradle發(fā)布Android library到maven倉(cāng)庫(kù)主要有兩種方式,一種是使用uploadArchives
约啊,另一種是使用publish
。下面分別對(duì)這兩種方式進(jìn)行介紹佣赖。
1.uploadArchives
uploadArchives
是一種比較老的發(fā)布library到maven倉(cāng)庫(kù)的方式恰矩,我們?cè)谛枰虬l(fā)布的Module
里的build.gradle
模塊里增加如下代碼:
關(guān)于
groupId
、artifactId
憎蛤、version
外傅,下圖進(jìn)行了詳細(xì)示例:repository
:即要把準(zhǔn)備發(fā)布的sdk發(fā)布到哪里,如果是發(fā)布到本地俩檬,那么就這里就填上本地的地址萎胰,如果是發(fā)布到maven倉(cāng)庫(kù),那么就填maven倉(cāng)庫(kù)的地址棚辽。這里的示例是發(fā)布到本地技竟,填寫(xiě)了本地的地址。
需要注意的是屈藐,
repository
中填寫(xiě)的路徑榔组,如果是本地路徑熙尉,那么要在路徑前面加上file://localhost
的前綴,否則會(huì)發(fā)布不成功搓扯。
然后在項(xiàng)目根目錄的命令行下執(zhí)行命令:
./gradlew uploadArchives
我們就可以在repository
所填寫(xiě)的地址下查看生成的SDK检痰。
上圖是生成的SDK文件的文件目錄,我們可以看到锨推,這里主要生成了兩個(gè)文件铅歼,一個(gè)是
aar
文件,另一個(gè)是pom
文件爱态,其他文件均是這兩個(gè)文件的加密文件谭贪。aar
文件我們都知道,那么pom
文件到底是什么呢锦担?我們不妨打開(kāi)pom
文件查看一下具體的內(nèi)容:pom
文件的內(nèi)容很清晰了,這里記錄了SDK的groupId
,artifactId
,version
慨削,不光如此洞渔,這里還記錄了一個(gè)非常重要的內(nèi)容,即SDK的依賴缚态,dependencies
節(jié)點(diǎn)下記錄的就是SDK的依賴磁椒,每一個(gè)dependency
節(jié)點(diǎn)記錄一個(gè)依賴。dependencies
依賴項(xiàng)是自動(dòng)生成的玫芦,記錄了SDK的依賴浆熔,當(dāng)該SDK被引用的時(shí)候,這些依賴會(huì)被傳遞
uploadArchives
方式和publish
方式的一個(gè)很大的區(qū)別就是uploadArchives
會(huì)自動(dòng)生成pom
文件里的dependencies
節(jié)點(diǎn)桥帆,使得SDK的依賴被成功傳遞医增,而publish
方式則需要自己手動(dòng)添加到pom
文件。
使用已發(fā)布的SDK
使用已發(fā)布的SDK很簡(jiǎn)單老虫,我們只需要進(jìn)行比普通的引用多一步叶骨,即添加maven倉(cāng)庫(kù)的路徑,我們?cè)诠こ痰?code>build.gradle的allprojects
下添加maven倉(cāng)庫(kù)的路徑:
maven {url '/Users/abc/.m2/repository/'}
然后在Module
的build.gradle
文件里正常引用:
implementation 'com.huya.hybrid:lizard:5.0.0-SNAPSHOT'
2.publish
使用publish
方式發(fā)布library需要使用maven-publish
插件祈匙。步驟如下:
首先在要發(fā)布的Module
下的build.gradle
文件同目錄下新建文件publish.gradle
忽刽,在該文件中新建一個(gè)publish
任務(wù):
apply plugin: 'maven-publish'
def getReleaseRepositoryUrl() {
return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
: "https://oss.sonatype.org/content/repositories/releases/"
}
def getSnapshotRepositoryUrl() {
return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
: "https://oss.sonatype.org/content/repositories/snapshots/"
}
def getRepositoryUsername() {
return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "admin"
}
def getRepositoryPassword() {
return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "admin123"
}
task sourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
publishing {
publications {
PublishAndroidAssetLibrary(MavenPublication) {
groupId 'com.huya.hybrid'
artifactId 'oak-webview-sdk'
version version
afterEvaluate {
artifact bundleReleaseAar
}
artifact sourcesJar
pom.withXml {
//在pom.xml添加依賴關(guān)系
def dependenciesNode = asNode().appendNode('dependencies')
//拿到所有編譯時(shí)的依賴
def dependenciesList = []
dependenciesList.addAll(configurations.implementation.allDependencies)
dependenciesList.addAll(configurations.api.allDependencies)
dependenciesList.each {
if (null != it.group) {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', 'compile')
}
}
}
}
}
def getRepositoryUrl() {
if (version != null && version.toLowerCase().endsWith("snapshot")) {
return getSnapshotRepositoryUrl()
} else {
return getReleaseRepositoryUrl()
}
}
boolean isJenkinsBuild = 0 != (System.getenv("BUILD_NUMBER") as Integer ?: 0)
String localMavenRepoPath = hasProperty("LOCAL_REPO") ? getProperty("LOCAL_REPO") : "${rootDir}/outputs/android/maven"
println("isJenkinsBuild=$isJenkinsBuild,repo=$localMavenRepoPath")
publishing {
repositories {
if (isJenkinsBuild) {
//這個(gè)是發(fā)布到線上倉(cāng)庫(kù)的功能支持
maven {
url getRepositoryUrl()
credentials {
username = getRepositoryUsername()
password = getRepositoryPassword()
}
}
} else {
//這個(gè)是發(fā)布到本地目錄功能支持
maven {
url localMavenRepoPath
}
}
}
}
首先看到publish任務(wù)的repository
模塊,該模塊確定了SDK發(fā)布的地址夺欲。
然后看到publish的
publications
模塊跪帝,該模塊確定了SDK的groupId
,artifactId
,version
等基本信息,還有一個(gè)非常重要的功能就是修改生成的pom
文件些阅∩〗#可以使用pom.withXml
進(jìn)行修改這里我們可以看到,首先為pom文件增加了
dependencies
節(jié)點(diǎn)扑眉,然后是通過(guò)configurations.api.allDependencies
和configurations.implementation.allDependencies
獲取api引用和implementation引用纸泄,然后為每一個(gè)這種引用增加一個(gè)depemdency
節(jié)點(diǎn)赖钞,在節(jié)點(diǎn)中設(shè)置groupId
,artifactId
聘裁,version
,scope
等屬性雪营,前幾個(gè)比較簡(jiǎn)單,后面這個(gè)scope
衡便,它有6種選擇献起,具體可以看這里,使用compile
即意味著镣陕,一旦引用了這個(gè)SDK谴餐,則pom
文件中dependency
內(nèi)scope
為compile
的依賴包都會(huì)被下載下來(lái)。所以對(duì)于SDK中想要傳遞的引用呆抑,scope需要使用complie
岂嗓,如不需要傳遞的引用,則可以使用provided
鹊碍。
然后在gradle.properties
里面可以設(shè)置version:
version=1.0.0-SNAPSHOT
在Module
的build.gradle
中引用publish.gradle
:
apply from: "publish.gradle"
最后再根目錄下命令行執(zhí)行:
./gradlew publish
最后生成的文件目錄如下:
pom文件:
當(dāng)該SDK被引用時(shí)厌殉,pom文件中
dependecy
節(jié)點(diǎn)的scope
為compile
的依賴都會(huì)被下載下來(lái)。
最后是使用侈咕,首先是跟uploadArchives
一樣添加maven
倉(cāng)庫(kù)地址公罕,這個(gè)不再介紹。然后是在Module
的build.gradle
下添加引用:
implementation ('com.huya.hybrid:lizard:6.0.0-SNAPSHOT'){transitive = true}
最后多的這個(gè){transitive = true}
用來(lái)顯式指出是否傳遞本身的依賴給宿主程序耀销。
參考
Maven publish plugin
https://developer.android.com/studio/build/dependencies
https://www.baeldung.com/maven-dependency-scopes