最近完成的一个小的任务是将Andorid的SDK发布到公司的maven仓库,供内部开发人员使用,这里记录一下完成这一小的任务学习的知识以及踩的坑。
使用gradle发布Android library到maven仓库主要有两种方式,一种是使用uploadArchives
,另一种是使用publish
。下面分别对这两种方式进行介绍。
1.uploadArchives
uploadArchives
是一种比较老的发布library到maven仓库的方式,我们在需要打包发布的Module
里的build.gradle
模块里增加如下代码:
关于
groupId
、artifactId
、version
,下图进行了详细示例:repository
:即要把准备发布的sdk发布到哪里,如果是发布到本地,那么就这里就填上本地的地址,如果是发布到maven仓库,那么就填maven仓库的地址。这里的示例是发布到本地,填写了本地的地址。
需要注意的是,
repository
中填写的路径,如果是本地路径,那么要在路径前面加上file://localhost
的前缀,否则会发布不成功。
然后在项目根目录的命令行下执行命令:
./gradlew uploadArchives
我们就可以在repository
所填写的地址下查看生成的SDK。
上图是生成的SDK文件的文件目录,我们可以看到,这里主要生成了两个文件,一个是
aar
文件,另一个是pom
文件,其他文件均是这两个文件的加密文件。aar
文件我们都知道,那么pom
文件到底是什么呢?我们不妨打开pom
文件查看一下具体的内容:pom
文件的内容很清晰了,这里记录了SDK的groupId
,artifactId
,version
,不光如此,这里还记录了一个非常重要的内容,即SDK的依赖,dependencies
节点下记录的就是SDK的依赖,每一个dependency
节点记录一个依赖。dependencies
依赖项是自动生成的,记录了SDK的依赖,当该SDK被引用的时候,这些依赖会被传递
uploadArchives
方式和publish
方式的一个很大的区别就是uploadArchives
会自动生成pom
文件里的dependencies
节点,使得SDK的依赖被成功传递,而publish
方式则需要自己手动添加到pom
文件。
使用已发布的SDK
使用已发布的SDK很简单,我们只需要进行比普通的引用多一步,即添加maven仓库的路径,我们在工程的build.gradle
的allprojects
下添加maven仓库的路径:
maven {url '/Users/abc/.m2/repository/'}
然后在Module
的build.gradle
文件里正常引用:
implementation 'com.huya.hybrid:lizard:5.0.0-SNAPSHOT'
2.publish
使用publish
方式发布library需要使用maven-publish
插件。步骤如下:
首先在要发布的Module
下的build.gradle
文件同目录下新建文件publish.gradle
,在该文件中新建一个publish
任务:
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添加依赖关系
def dependenciesNode = asNode().appendNode('dependencies')
//拿到所有编译时的依赖
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) {
//这个是发布到线上仓库的功能支持
maven {
url getRepositoryUrl()
credentials {
username = getRepositoryUsername()
password = getRepositoryPassword()
}
}
} else {
//这个是发布到本地目录功能支持
maven {
url localMavenRepoPath
}
}
}
}
首先看到publish任务的repository
模块,该模块确定了SDK发布的地址。
然后看到publish的
publications
模块,该模块确定了SDK的groupId
,artifactId
,version
等基本信息,还有一个非常重要的功能就是修改生成的pom
文件。可以使用pom.withXml
进行修改这里我们可以看到,首先为pom文件增加了
dependencies
节点,然后是通过configurations.api.allDependencies
和configurations.implementation.allDependencies
获取api引用和implementation引用,然后为每一个这种引用增加一个depemdency
节点,在节点中设置groupId
,artifactId
,version
,scope
等属性,前几个比较简单,后面这个scope
,它有6种选择,具体可以看这里,使用compile
即意味着,一旦引用了这个SDK,则pom
文件中dependency
内scope
为compile
的依赖包都会被下载下来。所以对于SDK中想要传递的引用,scope需要使用complie
,如不需要传递的引用,则可以使用provided
。
然后在gradle.properties
里面可以设置version:
version=1.0.0-SNAPSHOT
在Module
的build.gradle
中引用publish.gradle
:
apply from: "publish.gradle"
最后再根目录下命令行执行:
./gradlew publish
最后生成的文件目录如下:
pom文件:
当该SDK被引用时,pom文件中
dependecy
节点的scope
为compile
的依赖都会被下载下来。
最后是使用,首先是跟uploadArchives
一样添加maven
仓库地址,这个不再介绍。然后是在Module
的build.gradle
下添加引用:
implementation ('com.huya.hybrid:lizard:6.0.0-SNAPSHOT'){transitive = true}
最后多的这个{transitive = true}
用来显式指出是否传递本身的依赖给宿主程序。
参考
Maven publish plugin
https://developer.android.com/studio/build/dependencies
https://www.baeldung.com/maven-dependency-scopes