在项目的跟目录下新建一个 publish-maven.gradle 文件,内容如下:
apply plugin: 'maven-publish'
apply plugin: 'signing'
Properties localProperties = new Properties()
localProperties.load(project.rootProject.file('local.properties').newDataInputStream())
localProperties.each { name, value -> project.ext[name] = value
}
def mavenUsername = localProperties.getProperty("sonatype.username")
def mavenPassword = localProperties.getProperty("sonatype.password")
def projectGroupId = project.ext.groupId
def projectArtifactId = project.getName()
def projectVersionName = project.ext.has('version') ? project.ext.getProperty('version') : project.extensions.findByName("android")["defaultConfig"].versionName
def projectDescription = project.ext.has('description') ? project.ext.getProperty('description') : null
def projectGitUrl = project.ext.has('gitUrl') ? project.ext.getProperty('gitUrl') : null
def projectLicense = project.ext.has('license') ? project.ext.getProperty('license') : null
def projectLicenseUrl = projectLicense ? "https://opensource.org/licenses/${projectLicense.toString().replace(" ", "-")} " : null
def developerAuthorId = mavenUsername
def developerAuthorName = mavenUsername
def developerAuthorEmail = project.ext.has('authorEmail') ? project.ext.getProperty('authorEmail') : null
println("${mavenUsername} ${mavenPassword} - ${projectGroupId}:${projectArtifactId}:${projectVersionName}")
println("${projectLicense} - ${projectLicenseUrl}")
if (!mavenUsername || !mavenPassword || !projectGroupId || !projectArtifactId || !projectVersionName) {
println('error:missing parameter')
return
}
if (!projectDescription || !projectGitUrl || !projectLicense || !projectLicenseUrl || !developerAuthorId || !developerAuthorName || !developerAuthorEmail) {
println('warning:missing optional parameter')
}
def isAndroidProject = project.hasProperty('android')
if (isAndroidProject) {
println("Android project publish")
// Android 工程
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
task javadocsJar(type: Jar, dependsOn: androidJavadocs) {
archiveClassifier.set("javadoc")
from androidJavadocs.destinationDir
}
task sourcesJar(type: Jar) {
archiveClassifier.set("sources")
from android.sourceSets.main.java.srcDirs
}
} else {
println("Java project publish")
// Java 工程
task javadocsJar(type: Jar, dependsOn: javadoc) {
archiveClassifier.set("javadoc")
from javadoc.destinationDir
}
task sourcesJar(type: Jar) {
archiveClassifier.set("sources")
from sourceSets.main.allJava
}
}
tasks.withType(Javadoc).all {
options {
encoding "UTF-8"
charSet 'UTF-8'
author true
version true
links "http://docs.oracle.com/javase/11/docs/api"
if (isAndroidProject) {
linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
}
failOnError = false
}
enabled = false
}
artifacts {
archives javadocsJar, sourcesJar
}
publishing {
publications {
aar(MavenPublication) {
groupId = projectGroupId
artifactId = projectArtifactId
version = projectVersionName
// Tell maven to prepare the generated "*.aar" file for publishing
if (isAndroidProject) {
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
} else {
artifact("$buildDir/libs/${project.getName()}.jar")
}
artifact javadocsJar
artifact sourcesJar
pom {
name = projectArtifactId
description = projectDescription
// If your project has a dedicated site, use its URL here
url = projectGitUrl
licenses {
license {
name = projectLicense
url = projectLicenseUrl
}
}
developers {
developer {
id = developerAuthorId
name = developerAuthorName
email = developerAuthorEmail
}
}
// Version control info, if you're using GitHub, follow the format as seen here
scm {
connection = "scm:git:${projectGitUrl}"
developerConnection = "scm:git:${projectGitUrl}"
url = projectGitUrl
}
withXml {
def dependenciesNode = asNode().appendNode('dependencies')
configurations.api.allDependencies.each { dependency ->
if (!dependency.hasProperty('dependencyProject')) {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', dependency.group)
dependencyNode.appendNode('artifactId', dependency.name)
dependencyNode.appendNode('version', dependency.version)
}
}
}
}
}
}
repositories {
maven {
name = projectArtifactId
// release版本:发布版本即稳定版本,开发人员同一个版本多次发布,使用者不能自动load最新版本。
def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
//snapshots版本:快照版本即开发版本,版本号以-SNAPSHOT结尾,开发人员同一个版本多次发布,使用者可以自动load最新版本
def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
// You only need this if you want to publish snapshots, otherwise just set the URL
// to the release repo directly
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
// The username and password we've fetched earlier
credentials {
username mavenUsername
password mavenPassword
}
}
}
}
signing {
sign publishing.publications
}
ext {
groupId = 'io.gitee.osnetwork' // 项目组织的唯一标识符
description = 'Android Socket project' // 项目描述
gitUrl = 'https://gitee.com/projectes/IOSocket' // Git地址,不包含.git
authorEmail = '[email protected]' // 作者邮箱
license = 'MIT' // 开源协议,可选
version = '1.0.0' // 版本号
}
//gradle publish
apply from: "${rootProject.projectDir}/publish-maven.gradle"
当git提交上传项目时,local.properties 文件不会被提交,起到保护个人隐私的作用
#sonatype帐号
sonatype.username=hanyang
#sonatype密码
sonatype.password=********
#秘钥
signing.keyId=FC299E7B
#秘钥密码
signing.password=******
#GPG签名秘钥文件.gpg路径
signing.secretKeyRingFile=/Users/lihanyang/.gnupg/secring.gpg
在 Android studio 右侧,点击 Gradle 菜单,找到要提交的 module 库,先后执行 assemble 和 publish... 这两个任务,如下图:
点击 publish... 上传成功,会出现如下日志:
15:55:13: Executing 'publishAarPublicationToSocketRepository'...
Executing tasks: [publishAarPublicationToSocketRepository] in project ......
> Configure project :socket
......
MIT - https://opensource.org/licenses/MIT
Android project publish
> Task :socket:generatePomFileForAarPublication
> Task :socket:androidJavadocs SKIPPED
> Task :socket:javadocsJar UP-TO-DATE
> Task :socket:sourcesJar UP-TO-DATE
> Task :socket:signAarPublication
> Task :socket:publishAarPublicationToSocketRepository
BUILD SUCCESSFUL in 29s
5 actionable tasks: 3 executed, 2 up-to-date
Build Analyzer results available
15:55:42: Execution finished 'publishAarPublicationToSocketRepository'.
上传成功后,打开 Nexus Repository Manager 后台,登录 Sonatype 账号,然后点击左侧的 "Staging Repositories",如下图:
gradle 中会使用 implementation 来依赖某个第三方库,结构为:implementation GroupId:ArtifactId:Version
例如: implementation 'androidx.appcompat:appcompat:1.5.1'
是项目组织的唯一标识符,在实际开发中一般对应 JAVA 的包的结构,就是 main 目录里 java 的目录结构,如 ‘androidx.appcompat’。
是项目的唯一标识符,在实际开发中一般对应项目的名称,就是项目根目录的名称,例:appcompat。
是项目的版本号,例:1.0-SNAPSHOT 。其中 1.0 是版本号,SNAPSHOT 版本代表不稳定、尚处于开发中的版本。而衍生的有 Release 版本则代表稳定的版本。