Android发布库(jar/aar)到MavenCentral

Posted 殇神马

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android发布库(jar/aar)到MavenCentral相关的知识,希望对你有一定的参考价值。

一、前言:
由于Jcenter已经停止服务了,所以我们现在发布库一般是要发布到Maven Central;Maven Central和Jcenter一样也是一个公共的仓库,发布在上面的库可供自己和他人使用;android Studio 4.2开始,Google已经把MavenCentral作为gradle中的默认仓库配置;

二、发布库(jar/aar)到MavenCentral的流程

1.Sonatype Jira相关设置
我们首先要在 Sonatype Jira上注册一个账号;
然后在https://issues.sonatype.org/projects
上创建一个issure

在这里插入图片描述
在这里插入图片描述
groupId:我们最好是使用自己的gtihub地址,这样比较容易验证,如果是自己的个人的域名也可以;我填写的是:io.github.maqing-programmer

Project URL:我们在自己的GitHub上面新建一个仓库即可,这里填写这个仓库的地址即可;我这里填写的是:https://github.com/maqing-programmer/openlibrary

SCM url:上面的Project URL加上.gi即可,我这里填写的是:https://github.com/maqing-programmer/openlibrary.git

创建完issure以后,会有管理员处理你的这个issue,等待管理员回复你的issue,他会告诉你,要在你的github创建一个repo,repo的名字是这个issue的id,比如我的是OSSRH-69933。管理员回复我的如下图:

在这里插入图片描述
创建好之后,你需要添加评论,回复管理员已经创建好仓库;

在这里插入图片描述
回复管理员之后,等待这个issue的状态变成已解决RESOLVED状态。

在这里插入图片描述
这样,你就创建好了一个issue,用来承接对应group id下所有的库,Sonatype Jira
基本配置就完成了;

2.签名秘钥申请

下载gpg4win:

去GPG官网https://www.gpg4win.org/get-gpg4win.html 下载gpg4win-3.1.14.exe;
官网最新的版本是gpg4win-3.1.15,但是下载之后,后面打开kleopatra.exe
总是报错,所以就改成下载gpg4win-3.1.14了,打开kleopatra.exe也没有报错了;
下载之后,点击,进行安装即可;

安装完之后,桌面应该会出现kleopatra图标,我们点击打开,或者在gpg4win-3.1.14的安装目录下/bin/下找到kleopatra.exe点击打开也可;

打开kleopatra之后,新建秘钥

在这里插入图片描述
然后选择创建个人秘钥:
在这里插入图片描述
然后输入你的账号、邮箱,并且勾选Protect the generated key with a passphrase.(使用密码保护生成的密钥)在高级设置里可以设置更详细的,例如过期时间,但过期时间不可以太长,或报错。

在这里插入图片描述
点击新建,会要求设置一个密码,这个密码是私钥密码。后面会用到;
在这里插入图片描述
密码输入之后,点击下一步,就会创建成功;

新建完成之后在kleopatra界面会看到你创建的秘钥:

在这里插入图片描述

双击可查看

在这里插入图片描述
红框中的8位字母,后面是是要用的;
点击生成吊销证书按钮,保存下来你的吊销证书,

然后我们进入gpg4win-3.1.14的安装目录下/bin/,打开cmd,或者打开CMD,然后
定位到gpg4win-3.1.14的安装目录下/bin/下,然后输入
gpg --export-secret-keys -o secring.gpg命令接下来创建secring.gpg文件
这个secring.gpg文件,后面会用到;

然后回到主界面点击右键,在服务器发布:

在这里插入图片描述
3.gradle准备

我们进入Android Studio中,比如我们要上传的是一个Java Library,我们肯定是事先准备好了Android工程,然后在Android 工程中又新建了一个Java Library Module,Java Library Module下编写好库的代码之后,准备上传;
我们要准备一个上传的gradle脚本文件,在Android工程的根目录下,新建一个gradle文件,这里我们取名为publish_jar.gradle;

apply plugin: 'maven-publish'
apply plugin: 'signing'
task sourceJar(type: Jar) {
    classifier "sources"
    from   sourceSets.main.groovy.srcDirs
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier "javadoc"
    from javadoc.destinationDir
}

javadoc {
    description = "生成jar格式的javadoc。"
    // 只显示 protected 和 public 的类和成员
    options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED
    options.author = true
    options.version = true
    options.header = project.name
    // 静默javadoc检查(比如不支持@date会报错等),jdk 8+
    options.addStringOption('Xdoclint:none', '-quiet')
    // 防止本地打开中文乱码
    options.addStringOption("charset", "UTF-8")
    // suppress warnings due to cross-module @see and @link references;
    // note that global 'api' task does display all warnings.
    logging.captureStandardError LogLevel.INFO
    // suppress "## warnings" message
    logging.captureStandardOutput LogLevel.INFO
    // 编码一定要配置否则直接出错
    options.encoding = "UTF-8"
    options.charSet = "UTF-8"
}



ext {
    PUBLISH_GROUP_ID = "io.github.maqing-programmer" //
    PUBLISH_ARTIFACT_ID = 'plugin'            //项目名
    PUBLISH_VERSION = 2.2                   //版本号
}

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"
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            groupId = 'io.github.maqing-programmer'//Sonatype Jira上设置的groupId 
            artifactId = 'plugin'
            version = '2.2'
            from components.java

            artifact sourceJar
            artifact javadocJar

            pom {
                name = 'plugin'
                description = 'jiagu plugin'
                url = 'https://github.com/maqing-programmer/openlibrary'
                licenses {
                    license {
                        name = 'Apache License, Version 2.0'
                        url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                        distribution = 'repo'
                        comments = 'A business-friendly OSS license'
                    }
                }
                developers {
                    developer {
                        id = 'maqing'  //Sonatype Jira上的username
                        name = 'maqing' //Sonatype Jira上的username
                        email = '2856992713@qq.com'
                    }
                }
                scm {
                    //修改成你的Git仓库地址: https://github.com/maqing-programmer/openlibrary.git
                    connection = 'scm:git:github.com/maqing-programmer/openlibrary.git'
                    developerConnection = 'scm:git:ssh://github.com/maqing-programmer/openlibrary.git'
                    //分支地址:
                    url = 'https://github.com/maqing-programmer/openlibrary/tree/master'
                }
            }
        }
    }

    repositories {
        maven {
            // any other name that's descriptive for you
            name = "Releases"

            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 ossrhUsername
                password ossrhPassword
            }
        }
    }
}

signing {
    sign publishing.publications.mavenJava
}

然后在Android工程的根目录下的local.properties里面添加如下内容;

signing.keyId=新建的秘钥的后8位
signing.password=新建密钥时设置的密码
signing.secretKeyRingFile=D\\:\\\\key\\\\secring.gpg(生成的secring.gpg的位置)
ossrhUsername=Sonatype注册的用户名
ossrhPassword=Sonatype注册的密码

然后在你要提交的module下的build.gradle文件中,尾部追加如下代码:

 apply from: '../publish_jar.gradle'

然后同步(Sync)即可

4.执行打包和上传

上传之前首先要打包我们的Java Library的源码为jar文件,在Android Studio中右侧的gradle窗口中的task中找到想要提交的Module;然后执行build任务
在这里插入图片描述
build任务执行完毕之后,在Java Library目录下build/libs/目录下会有打包好的jar文件

在这里插入图片描述
然后再点击该module下的publishReleasePublicationToReleasesRepository任务

在这里插入图片描述
发布任务执行完毕之后,进入Nexus Repository Manager 上,登录,登录的账号就是sonatype的账号,登录之后左侧的菜单中找到Staging Repositories,点击该菜单,会看到我们的groupId对应的该库的临时仓库,并且会有编号,如果有个多个临时仓库,就会有多个groupId-编号的临时仓库

在这里插入图片描述
在这里插入图片描述
然后选中我们的库对应的临时仓库,点击close关闭该库

在这里插入图片描述
close成功之后,然后再点击release,释放该包,释放该包成功之后,这个临时仓库就会不存在了;然后等待两个小时候之后,然后我们在https://search.maven.org/ 上就可以搜索到我们的这个库了,我么可以通过groupId,
或者通过库名来搜索;

在这里插入图片描述
5.使用该库

如果是一个普通的Java Library库,你可以直接
implementation 'io.github.maqing-programmer:plugin:2.0’来使用该库;

我们其实可以点击MavenCentral上的这个库的版本号,进入这个库的详情,
右边是有这个库在各个构建工具中如何引用的方法:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如上图所示在gradle中就是
implementation ‘io.github.maqing-programmer:plugin:2.0’
使用这种引用方式;

上面就是上传一个Java Library(jar)库到MavenCentral库中的过程;

上传一个aar库到MavenCentral

上传aar库到mavenCentral基本步骤和上传jar库是一样的,不同的是我们上传的 moule类型以及gradle准备中的上传脚本不一样;

1.新建要上传的Android Library Module

首先我们要新建一个Android工程,然后新建一个Android Library Module,新建的Android Library Module好像默认是没有res资源目录,我么可以自己在src/main下新建一个res资源目录,或者直接将Android工程主Module下的res资源目录拷贝到Android Library Module下src/main下;
然后编写我们的库代码,编写好库代码之后,我们在Android Studio右侧gradle task
窗口,找到我们的Android Library Module下的Tasks下的build中的build任务,执行完毕之后,在Android Library Module中的build/outputs/aar目录下就会生成我们的aar库文件;

在这里插入图片描述
2.gradle准备

我们要准备一个上传的gradle脚本文件,在Android工程的根目录下,新建一个gradle文件,这里我们取名为publish_aar.gradle;

apply plugin: 'maven-publish'
apply plugin: 'signing'

task androidSourcesJar(type: Jar) {
    classifier = 'sources'
//    from sourceSets.main.java.source
    from android.sourceSets.main.java.source
}

ext {
    PUBLISH_GROUP_ID = "io.github.maqing-programmer" //项目包名
    PUBLISH_ARTIFACT_ID = 'mylibrary'            //项目名
    PUBLISH_VERSION = 2.0                   //版本号
}

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"
}


publishing{
    publications{
        release(MavenPublication) {
            // The coordinates of the library, being set from variables that
            // we'll set up in a moment
            groupId "io.github.maqing-programmer"
            artifactId "mylibrary"
            version '2.0'

            // Two artifacts, the `aar` and the sources
            artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
            artifact androidSourcesJar
            // Self-explanatory metadata for the most part
            pom {
                name = PUBLISH_ARTIFACT_ID
                description = '你的项目描述'
                // If your project has a dedicated site, use its URL here
                url = 'https://github.com/maqing-programmer/openlibrary'
                licenses {
                    license {
                        //协议类型,一般默认Apache License2.0的话不用改:
                        name = 'The Apache License, Version 2.0'
                        url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                developers {
                    developer {
                        id = 'maqing'
                        name = 'maqing'
                        email = '2856992713@qq.com'
                    }
                }
                // Version control info, if you're using GitHub, follow the format as seen here
                scm {
                    //修改成你的Git地址: https://github.com/maqing-programmer/openlibrary.git
                    connection = 'scm:git:github.com/maqing-programmer/openlibrary.git'
                    developerConnection = 'scm:git:ssh://github.com/maqing-programmer/openlibrary.git'
                    //分支地址:
                    url = 'https://github.com/maqing-programmer/openlibrary/tree/master'
                }
                // A slightly hacky fix so that your POM will include any transitive dependencies
                // that your library builds upon
                withXml {

                    def dependenciesNode = asNode().appendNode('dependencies')

                    project.configurations.implementation.allDependencies.each {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                    }

                }
            }
        }
    }
    repositories {
        // The repository to publish to, Sonatype/MavenCentral
        maven {
            // This is an arbitrary name, you may also use "mavencentral" or
            // any other name that's descriptive for you
            name = "Releases"

            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 ossrhUsername
                password ossrhPassword
            }
        }
    }
}

signing {
    sign publishing.publications
}

然后我们在Android根目录下的gradle.properties下增加如下配置:

VERSION_NAME=1.0.2
VERSION_CODE=2
GROUP_ID=io.github.maqing-programmer

POM_DESCRIPTION=Android Download Library
POM_URL=https://github.com/maqing-programmer/openlibrary
POM_SCM_URL=https://github.com/maqing-programmer/openlibrary/tree/master
POM_SCM_CONNECTION=scm:git:github.com/maqing-programmer/openlibrary.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://github.com/maqing-programmer/openlibrary.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=Apache 2.0
POM_DEVELOPER_ID=maqing
POM_DEVELOPER_NAME=maqing

当然和上传jar库一样,也要在Android工程根目录下的local.properties下添加如下配置

signing.keyId=新建的秘钥的后8位
signing.password=新建密钥时设置的密码
signing.secretKeyRingFile=D\\:\\\\key\\\\secring.gpg(生成的secring.gpg的位置)
ossrhUsername=Sonatype注册的用户名
ossrhPassword=Sonatype注册的密码

然后在Android Library Module的build.gradle尾部添如下代码

apply from: "${rootProject.projectDir}/publish_aar.gradle"

然后同步(sync)一下;

3.上传aar库到mavenCentral

我们在Android Studio右侧的gradle task窗口中,找到我们这个Android Library Module,然后找到该Module下的Tasks下的publishing任务,然后点击该任务下的publishReleasePublicationToReleasesRepository;

在这里插入图片描述
任务执行完毕之后,后续步骤就和上传jar库中的后续步骤是一样的,去Nexus Repository Manager上执行相应的close、release操作,然后等待2个小时,然后我们在https://search.maven.org/ 上就可以搜索到我们的这个库了,我么可以通过groupId,或者通过库名来搜索;然后就可以使用该aar库了,gradle中使用方式同jar库;

    implementation 'io.github.maqing-programmer:mylibrary:2.0'

以上就是aar库上传至mavenCentral的过程;

注意:发布到MavenCentral上的库是无法删除的,你也无法重新发布一个相同版本号的库,你只能发布一个其他版本号的库

文章内容参考:

发布Android库到MavenCentral教程

Android库发布到Maven Central全攻略

以上是关于Android发布库(jar/aar)到MavenCentral的主要内容,如果未能解决你的问题,请参考以下文章

Android 库 (jar/aar) 可以用于 Xamarin 中的 iOS

[Android][Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法

Android端代码打包成jar包/aar形式

Android如何将一个Demo或者app打包成aar或jar提供给其他应用使用

处理Gradle依赖冲突

如何在 Android Studio 4.2 上导入 .AAR 模块