JCenter宣布停用后,今后只能发布到Maven Central,相对JCenter,首次发布到Maven Central要麻烦很多
注册Sonatype账号
https://issues.sonatype.org/secure/ForgotLoginDetails.jspa
创建问题
填写项目信息,Group Id
可以填自己的域名,或者com.github.自己的用户名
,后面会验证所有权
验证Group Id
几分钟后会有一个机器人回复,要求验证域名的所有权
- 用域名作为Group Id:域名解析一个TXT记录,内容就是当前问题编号
- 用Github用户名作为Group Id:创建一个名称为当前问题编号的仓库
将问题标记为打开
等待几分钟会回复验证成功,就可以上传项目了
发布项目
在要工程根目录创建publish.gradle
,粘贴模板,此模板支持Android、Java、Kotlin、Gradle Pluginpublish.gradle
代码地址:https://gist.github.com/xiandanin/6a215a24acee9e8194bc4668b3e8f1331
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133apply plugin: 'maven-publish'
apply plugin: 'signing'
Properties localProperties = new Properties()
// 合并local.properties
localProperties.load(project.rootProject.file('local.properties').newDataInputStream())
localProperties.each { name, value -> project.ext[name] = value }
Map<String, String> projectProperties = new HashMap<>()
// 合并project.ext
projectProperties.putAll(project.ext.getProperties())
// 合并rootProject.ext
rootProject.ext.getProperties().each { name, value -> if (!projectProperties.containsKey(name)) projectProperties.put(name, value) }
//println(properties)
def mavenUsername = localProperties.getProperty("sonatype.username")
def mavenPassword = localProperties.getProperty("sonatype.password")
def projectGroupId = projectProperties.get('groupId')
def projectArtifactId = project.getName()
def projectVersionName = projectProperties.getOrDefault('version', project.extensions.findByName("android")["defaultConfig"].versionName)
def projectDescription = projectProperties.get('description')
def projectGitUrl = projectProperties.get('gitUrl')
def projectLicense = projectProperties.get('license')
def projectLicenseUrl = projectLicense ? "https://opensource.org/licenses/${projectLicense.toString().replace(" ", "-")} " : null
def developerAuthorId = mavenUsername
def developerAuthorName = mavenUsername
def developerAuthorEmail = projectProperties.get('authorEmail')
println("${mavenUsername} ${mavenPassword} - ${projectGroupId}:${projectArtifactId}:${projectVersionName}")
println("${projectLicense} - ${projectLicenseUrl}")
if (!projectGroupId || !projectArtifactId || !projectVersionName) {
println("${project.name} 缺少项目信息")
return
}
if (!mavenUsername || !mavenPassword || !localProperties.containsKey("signing.keyId") || !localProperties.containsKey("signing.password") || !localProperties.containsKey("signing.secretKeyRingFile")) {
println("${project.name} 缺少认证信息")
return
}
if (!projectDescription || !projectGitUrl || !projectLicense || !projectLicenseUrl || !developerAuthorId || !developerAuthorName || !developerAuthorEmail) {
println("${project.name} 缺少项目描述信息")
}
android {
publishing {
singleVariant("release") {
withSourcesJar()
withJavadocJar()
}
}
}
afterEvaluate {
publishing {
publications {
aar(MavenPublication) {
from components.release
groupId = projectGroupId
artifactId = projectArtifactId
version = projectVersionName
pom {
name = projectArtifactId
description = projectDescription
// If your project has a dedicated site, use its URL here
url = projectGitUrl
if (projectLicense) {
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 { xmlProvider ->
def node = xmlProvider.asNode()
def getAt = node.getAt('dependencies')
def dependenciesNode
if (getAt == null) {
dependenciesNode = node.appendNode('dependencies')
} else {
dependenciesNode = getAt[0]
}
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
def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
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
}
在要发布的Library工程下的build.gradle
最后引用发布模板
1 | apply from: '../publish.gradle' |
在工程根目录的build.gradle
最后添加项目信息
1 | ext { |
创建密钥
- Gpg4win :https://www.gpg4win.org/download.html
- 签名凭证 :https://docs.gradle.org/current/userguide/signing_plugin.html
创建证书
生成密钥对
创建个人OpenPGP密钥对
勾选Protect the generated key with a passphrase.
,输入密码
复制指纹后8位作为signing.keyId
生成撤销证书
右键证书,在服务器上发布,最后会发布在http://keys.gnupg.net
右键Backup Secret Keys...
导出私钥证书,后缀名改为gpg
填写认证信息
将Sonatype账号和密钥信息填写到local.properties
,signing.secretKeyRingFile
就是最后导出的.gpg
路径
1 | sonatype.username= |
发布
执行publish
任务,或者命令行执行gradlew publish
任务执行完成后,登录https://s01.oss.sonatype.org/#stagingRepositories,选中刚刚上传的提交,点击Close
无报错提示Repository Closed
说明执行完成,点击Release
,等待几十分钟就会同步到Maven Central
了
首次发布同步
因为这个Group Id是首次发布,发布项目后,要手动通知同步到Maven Central,将Already Synced to Central
标记为Yes
,等待几个小时就可以在Maven Central看到项目了