最近在给我的开源库Aria升级版本时,发现Bintray已经无法上传库了,网上查了下,发现Jcenter要停止服务了,从2021年5月1号还要删除所有开发者上传的包,因此就需要将库移到其它的托管中心,谷歌建议开发者们将库托管到mavenCentral
一、注册
首先,先去Sonatype Jira这个地址注册一个SonatypeJira的账号;
其次,账号创建后,登录,然后在这个页面https://issues.sonatype.org/projects 点击Create创建一个issue,如下图:
二、域名验证
创建完成后,隔段时间,系统就会告诉你需要验证下域名
创建一个TXT解析
然后回复下
审核成功后,系统会告诉你审核成功,并且工程的状态会变成RESOLVED
三、配置GPG
3.1 Mac 配置
3.1.1下载 macGPG (可视化)或 GunPG for OS X(命令行,建议使用这个)
GnuPG - Download
3.1.2 创建证书文件
在终端中输入
加密方式选择RSA and RSA,长度输入4096,过期时间直接回车不用管,然后输入一个user ID并且提供一个邮箱,我直接用的我sonatype的用户名和邮箱。最后一步输入’O’,表示OK。
之后会弹出一个对话框,让输入密码。
创建完成后,会在~/.gnupg/openpgp-revocs.d/
目录下创建一个.rev文件,记住pub的末尾8位。
3.1.3 secring.gpg文件
终端中输入命令
gpg --export-secret-keys -o secring.gpg
|
输入证书密码
3.1.4 发送密钥的keyserver
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys 证书指纹
|
也就是创建证书时的pubID
如果创建成功,会收到一份邮件
或者使用下面命令查看证书是否上传成功
3.1.5 保存证书文件
将secring.gpg
、`指纹信息、证书密码保存下来
将来换电脑可以通过搜索密钥,重新倒入证书信息
3.2 win 配置
3.2.1 下载 GPG
打开 https://www.gpg4win.org/ 下载 GPG,然后一步步安装。
安装完成后会看到桌面上多了个 Kleopatra 图标,这个程序是 GnuPG 的前端程序,这里我们将它打开。
3.2.2 配置密钥对
打开 Kleopatra 后,点击新建密钥对
输入姓名和邮箱
最后确认新建
过程中需要自己输入一个8位以上的密码,请记住该密码,后面还需要用到。 输入完成以后就会提示下面信息。
3.2.3上传公钥到 GPS key-servers
打开命令提示符窗口,输入下面命令将证书发送到远程服务器
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys 243EFB60D8F930B391CA194EA40663B00BDC6CA1
|
四、编写上传脚本
4.1 添加依赖
修改项目根build.gradle
,添加
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.4.30" // kotlin 文档引擎
|
buildscript { ext.kotlin_version = "1.4.30" repositories { google() mavenCentral() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.5.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.4.30" } }
|
4.2 配置sonatype信息
打开local.properties
,添加以下参数
signing.keyId=刚才获取的秘钥后8位 signing.password=步骤4中设置的密码 signing.secretKeyRingFile=刚才生成的secring.gpg文件路径 ossrhUsername=sonatype用户名 ossrhPassword=sonatype密码
|
4.3 配置打包信息
修改项目根build.gradle
,添加
ext { website = 'https://github.com/AriaLyy/KeepassA'
mavenCentralUserID = 'xxx' mavenCentralUserName = 'xxx' mavenCentralGroupId = 'me.laoyuyu.keepassa' mavenCentralEmail = 注册邮箱 mavenCentralLicences = 'MPL-2.0' mavenCentralLicencesURL = 'http://mozilla.org/MPL/2.0/' mavenCentralConnection = 'scm:git:github.com/用户名/项目名.git' mavenCentralDeveloperConnection = 'scm:git:ssh://github.com/用户名/项目名.git' mavenCentralTreeURL = 'https://github.com/AriaLyy/项目名/tree/master'
}
|
4.4 编写脚本
创建一个名为mavenCentral-release.gradle
的脚本文件,需要grade 3.6以上的版本
需要grade 3.6以上的版本。
Android脚本打包
maven-publish使用
apply plugin: 'maven-publish' apply plugin: 'signing'
ext { PUBLISH_GROUP_ID = rootProject.ext.mavenCentralGroupId }
tasks.withType(GroovyCompile) { groovyOptions.encoding = "UTF-8" }
tasks.withType(JavaCompile) { options.encoding = "UTF-8" }
tasks.withType(Javadoc) { if(JavaVersion.current().isJava9Compatible()) { options.addBooleanOption('html5', true) } options { encoding "UTF-8" charSet 'UTF-8' links "http://docs.oracle.com/javase/7/docs/api" addStringOption('Xdoclint:none', '-quiet') } }
ext["signing.keyId"] = '' ext["signing.password"] = '' ext["signing.secretKeyRingFile"] = '' ext["ossrhUsername"] = '' ext["ossrhPassword"] = ''
File secretPropsFile = project.rootProject.file('local.properties') if (secretPropsFile.exists()) { println "Found secret props file, loading props" Properties p = new Properties() p.load(new FileInputStream(secretPropsFile)) p.each { name, value -> ext[name] = value } } else { println "No props file, loading env vars" }
static def localMavenRepo() { 'file://' + new File(System.getProperty('user.home'), '.m2/repository').absolutePath }
def getReleaseRepositoryUrl() { return isLocal() ? localMavenRepo() : hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL : 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/' }
def getSnapshotRepositoryUrl() { return isLocal() ? localMavenRepo() : hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL : 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
def isLocal(){ return ISLOCAL == 'true' }
afterEvaluate { project ->
if (isLocal()) { println("上传到本地仓库") } else { println("上传到中央仓库") } publishing { def isAndroidProject = project.plugins.hasPlugin('com.android.application') || project. plugins. hasPlugin('com.android.library') publications { release(MavenPublication) { groupId PUBLISH_GROUP_ID artifactId PUBLISH_ARTIFACT_ID version PUBLISH_VERSION
if (isAndroidProject) { generateReleaseBuildConfig.enabled = false generateDebugBuildConfig.enabled = false generateReleaseResValues.enabled = false generateDebugResValues.enabled = false from components.release
def variants = project.android.libraryVariants.findAll { it.buildType.name.equalsIgnoreCase('debug') }
def getAndroidSdkDirectory = project.android.sdkDirectory
def getAndroidJar = "${getAndroidSdkDirectory}/platforms/${project.android.compileSdkVersion}/android.jar"
task androidJavadocs(type: Javadoc, dependsOn: assembleDebug) { println("开始打包aar") source = variants.collect { it.getJavaCompileProvider().get().source } classpath = files( getAndroidJar, project.file("build/intermediates/classes/debug") ) doFirst { classpath += files(variants.collect { it.javaCompile.classpath.files }) } options { links("http://docs.oracle.com/javase/7/docs/api/") linksOffline("http://d.android.com/reference", "${getAndroidSdkDirectory}/docs/reference") encoding "UTF-8" charSet 'UTF-8' addStringOption('Xdoclint:none', '-quiet') }
exclude '**/R.java' exclude "**/BuildConfig.class" }
def cleanJavadocTask = task("cleanJavadocTask", type: Delete) { delete androidJavadocs.destinationDir } as Task project.clean.dependsOn(cleanJavadocTask)
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { classifier = 'javadoc' from androidJavadocs.destinationDir baseName "${JAR_PREFIX}${project.name}" }
task androidSourcesJar(type: Jar) { classifier = 'sources' from project.android.sourceSets.main.java.source baseName "${JAR_PREFIX}${project.name}"
exclude "**/R.class" exclude "**/BuildConfig.class" }
task androidLibraryJar(type: Jar, dependsOn: compileDebugJavaWithJavac ) { from compileDebugJavaWithJavac.destinationDir from 'build/tmp/kotlin-classes/debug/'
exclude '**/R.class' exclude '**/R$*.class' exclude "**/BuildConfig.class" baseName "${JAR_PREFIX}${project.name}-cache" }
artifact androidLibraryJar artifact androidSourcesJar artifact androidJavadocsJar } else if (project.plugins.hasPlugin('java')) { from components.java
task sourcesJar(type: Jar, dependsOn: classes) { classifier = 'sources' from sourceSets.main.allSource }
task javadocsJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from javadoc.destinationDir }
artifact sourcesJar artifact javadocsJar }
pom { name = PUBLISH_ARTIFACT_ID description = rootProject.ext.desc url = rootProject.ext.website licenses { license { name = rootProject.ext.mavenCentralLicences url = rootProject.ext.mavenCentralLicencesURL } } developers { developer { id = rootProject.ext.mavenCentralUserID name = rootProject.ext.mavenCentralUserName email = rootProject.ext.mavenCentralEmail } } scm { connection = rootProject.ext.mavenCentralConnection developerConnection = rootProject.ext.mavenCentralDeveloperConnection url = rootProject.ext.mavenCentralTreeURL } } } } repositories { maven { name = "mavencentral"
def releasesRepoUrl = getReleaseRepositoryUrl() def snapshotsRepoUrl = getSnapshotRepositoryUrl() url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
credentials { username ossrhUsername password ossrhPassword } } } } signing { sign publishing.publications } }
|
在module的build.gradle
文件中添加脚本
ext{ PUBLISH_ARTIFACT_ID = 组件名 PUBLISH_VERSION = 组件版本 } apply from: 'mavenCentral-release.gradle'
|
4.5 上传
在build 文件中添加脚本
apply from: 'mavenCentral-release.gradle'
|
创建运行配置
创建一个Gradle命令
然后创建一个上传任务
点击该任务的执行按钮便可自动上传
TIP,多module上传:
如果需要同时上传多个包,可以在终端中执行以下命令:
./gradlew clean build publishReleasePublicationToMavencentralRepository
|
或者在主工程目录创建一个gradle命令,运行就相当于执行了所有module的maven上传脚本
TIP,本地发布:
由于mavencentral
同步很慢,因此本地测试就很有必要,执行publishReleasePublicationToMavenLocal
便可以上传到本地的maven仓库。
4.6 进行发布
上传成功后,打开Nexus Repository Manager,登录你的sonatype账号,在左侧Staging Repositories
页面找到你的group id,选中,点击上边的close,等待几分钟十几分钟后刷新状态,等其状态变为closed后,再点击Release,则所有人都用使用你的库了。
4.7 Issues 中回复已经 Release 完成
4.8 查看自己的项目
发布成功后可以进入 https://search.maven.org 网址查询自己发布的 Jar,如果未查到等几个小时再此查询。
参考地址
使用 Maven Publish 插件 | Android 开发者 | Android Developers
发布Android库到MavenCentral教程 - 知乎 (zhihu.com)
JCenter 弃用和服务终止 | Android 开发者 | Android Developers
将 Java 项目推送到 Maven 中央仓库实践 | 超级小豆丁 (mydlq.club)