如何发布Android Library到maven私有仓库

简介: 在我们的项目架构中,一定存在一些基础的模块,这些模块可以在多个app上通用,这种情况我们一般会将这些模块封装成Android Library统一维护,并上传到仓库方便其他小组使用。仓库可以选择如mavenCentral这类公开的仓库,但是我们一般选择搭建自己的maven私有仓库,比如:Sonatype Nexus。本文就一步步的教大家如何将Android Library发布到maven私有仓库。

前言


在我们的项目架构中,一定存在一些基础的模块,这些模块可以在多个app上通用,这种情况我们一般会将这些模块封装成Android Library统一维护,并上传到仓库方便其他小组使用。仓库可以选择如mavenCentral这类公开的仓库,但是我们一般选择搭建自己的maven私有仓库,比如:Sonatype Nexus。本文就一步步的教大家如何将Android Library发布到maven私有仓库。


添加maven仓库配置


在项目的根目录下的gradle.properties中添加私有仓库的配置,如下:


# 包信息(包名,及Maven的group,必填)
PROJ_GROUP=com.xxx.xxx                    
# 项目的描述(描述性信息,不影响maven上传)
PROJ_WEBSITEURL=http://xxxxx
PROJ_ISSUETRACKERURL=http://xxxxx
PROJ_VCSURL=xxxxx
PROJ_DESCRIPTION=xxxx
# Licence信息(严格按下面填写,不要变)
PROJ_LICENCE_NAME=The Apache Software License, Version 2.0
PROJ_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
PROJ_LICENCE_DEST=repo
# Developer 信息(开发者信息,不影响maven上传)
DEVELOPER_ID=xxxx
DEVELOPER_NAME=xxxx
DEVELOPER_EMAIL=xxx@xxx.com
#仓库地址(要提交的本地仓库地址)
#快照库
SNAPSHOT_REPOSITORY_URL=http://xxxx/nexus/content/repositories/snapshots/
#正式库
RELEASE_REPOSITORY_URL=http://xxxx/nexus/content/repositories/releases/
复制代码


将这部信息配置在根目录的gradle.properties中是因为我们一个项目可能存在多个Android Library需要上传到maven,这样就不用在每个module下都配置一遍。

另外还需要配置用户名和密码,但是因为这是敏感信息,一般我们放在local.properties中,这个文件一般会加入.gitignore被git忽略,这样就不会上传到代码仓库中


#maven账号
USERNAME=xxxx
#maven密码
PASSWORD=xxxx
复制代码


最后还需要在Android Library下的gradle.properties中配置:


#名称(最好与PROJ_ARTIFACTID相同)
PROJ_NAME=xxx
#模块名(maven的artifactId)
PROJ_ARTIFACTID=xxxx
PROJ_POM_NAME=Local Repository
复制代码


编写发布代码


首先在Android Library下的build.gradle中添加maven插件


apply plugin: 'maven'
复制代码


然后就可以编写发布代码了,完整代码如下:


def isReleaseBuild() {
    return android.defaultConfig.versionName.contains("SNAPSHOT") == false
}
def sonatypeRepositoryUrl
if (isReleaseBuild()) {
    sonatypeRepositoryUrl = RELEASE_REPOSITORY_URL
} else {
    sonatypeRepositoryUrl = SNAPSHOT_REPOSITORY_URL
}
afterEvaluate { project ->
    uploadArchives {
        repositories {
            mavenDeployer {
                //beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
                pom.artifactId = PROJ_ARTIFACTID
                Properties properties = new Properties()
                properties.load(project.rootProject.file('local.properties').newDataInputStream())
                repository(url: sonatypeRepositoryUrl) {
                    authentication(userName: properties.getProperty("USERNAME"), password: properties.getProperty("PASSWORD"))
                }
                pom.project {
                    name PROJ_NAME
                    groupId PROJ_GROUP
                    version android.defaultConfig.versionName
//                    scm {
//                        url POM_SCM_URL
//                        connection POM_SCM_CONNECTION
//                        developerConnection POM_SCM_DEV_CONNECTION
//                    }
                    licenses {
                        license {
                            name PROJ_LICENCE_NAME
                            url PROJ_LICENCE_URL
                            distribution PROJ_LICENCE_DEST
                        }
                    }
                    developers {
                        developer {
                            id DEVELOPER_ID
                            name DEVELOPER_NAME
                        }
                    }
                }
            }
        }
    }
//    signing {
//        required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
//        sign configurations.archives
//    }
    task androidJavadocs(type: Javadoc) {
        failOnError false
        source = android.sourceSets.main.java.source
        options {
            links "http://docs.oracle.com/javase/7/docs/api/"
            linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
        }
        classpath += project.android.libraryVariants.toList().first().javaCompile.classpath
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    }
    task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
        classifier = 'javadoc'
        //basename = artifact_id
        from androidJavadocs.destinationDir
    }
    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.srcDirs
    }
    artifacts {
        //archives packageReleaseJar
        archives androidSourcesJar
        archives androidJavadocsJar
    }
}
复制代码


发布到maven仓库


在Android studio右侧栏的gradle中选择要发布的Module,找到定义好的task,双击运行即可,如图


网络异常,图片无法展示
|


多个Android Library发布问题处理


上面我们提到,可以在一个项目中同时维护多个Android Library,但是按照上面的步骤发布的时候就会失败,问题如下:


Could not transfer artifact xxx from/to remote (http://xxx): Failed to transfer file: http://xxx. Return code is: 400, ReasonPhrase: Bad Request.


仔细观察gradle日志就会发现,当我们通过上面方式发布其中一个Android Library时,项目所有的Android Library都会重新编译并发布,但是其它Android Library并没有改变,所以没有升级版本,maven仓库如果发现发布了同样的版本(一般release仓库会有这样的设置,防止误操作导致问题)就会返回上面的错误。

一个解决方法是通过命令进行发布:


./gradlew xxx:uploadArchives
复制代码


这里xxx就是模块名,这样就会只编译发布这一个模块。

当然我们也可以通过修改发布代码来解决这个问题,在build.gradle中添加一个task如下:


task mavenUploadxxx (dependsOn: uploadArchives){
    group 'upload'
}
复制代码


同样这里xxx替换成模块名,这里我们将这个task放在了upload这个组里,如果不设置会默认放在other组里,但是这个组里task比较多,找起来不方便。

sync同步后在gradle的面板中对应的Module的upload组中就会发现多出一个mavenUploadxxx的task,双击执行这个task就会只编译发布这个Android Library。


使用Library


使用就比较简单了,首先添加仓库


allprojects {
    repositories {
        ...
        maven {
            url 'http://xxx/nexus/content/groups/public/'
        }
    }
}
复制代码


然后在项目的build.gradle中添加依赖就可以了。


问题总结


在这个过程中也遇到了一些问题,这里简单总结一下:


1、发布到Snapshot的时候返回400错误:


Return code is: 400, ReasonPhrase: Bad Request.


这是因为版本名错了,发布到Snapshot的版本格式必须是x.x.x-SNAPSHOT,“-SNAPSHOT”必须在后面,否则会报400错误。

注意:相关错误,如发布到release的版本中有“-SNAPSHOT“也会报错;release不允许重复发布,所以如果已经有这个项目的这个版本,再次发布就会出错,而Snapshot一般支持重复发布


2、发布的时候返回401错误:


Return code is: 401, ReasonPhrase: Unauthorized

这是因为没有配置用户名密码,或配置错了。 Sonatype Nexus默认用户名admin密码admin123,但是建议及时修改。


3、Sonatype Nexus中仓库:


public:仓库组。代理其他仓库,用于外部引用。(即如果要使用Maven引入项目,则maven中心配置成这个仓库的url)

snapshot:快照库。用于提交快照版本,需要用户名密码。

release:正式库。用于提交正式版本,需要用户名密码。



目录
相关文章
|
3月前
|
敏捷开发 Java 持续交付
阿里云云效产品使用合集之maven仓库是否可以代替自建的Nexus
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
4月前
|
Java Linux Maven
Maven 仓库
Maven仓库管理构件(如JARs):本地仓库在首次执行时创建,默认位于`%USER_HOME%/.m2/repository/`;远程仓库包括中央仓库,存放大量开源Java构件,可在线浏览<http://search.maven.org/>。若本地缺失构件,Maven会从远程下载至本地。可通过settings.xml配置本地仓库路径。
|
1月前
|
XML 安全 Java
【Maven】依赖管理,Maven仓库,Maven核心功能
【Maven】依赖管理,Maven仓库,Maven核心功能
548 3
|
3月前
|
开发工具 Android开发
解决Android运行出现NDK at /Library/Android/sdk/ndk-bundle did not have a source.properties file
解决Android运行出现NDK at /Library/Android/sdk/ndk-bundle did not have a source.properties file
169 4
解决Android运行出现NDK at /Library/Android/sdk/ndk-bundle did not have a source.properties file
|
3月前
|
Java 开发工具 Maven
Flutter和Android中覆盖gradle中的repositories仓库地址
Flutter和Android中覆盖gradle中的repositories仓库地址
195 4
|
3月前
|
敏捷开发 JavaScript Java
阿里云云效产品使用合集之如何进行Maven私有仓库迁移
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
4月前
|
Java Maven
maven开源仓库
maven开源仓库
116 6
|
4月前
|
Java Linux Maven
Maven 仓库
Maven仓库管理构件,包括依赖和插件。有本地、中央和远程三种类型。本地仓库在首次运行时创建,默认在用户目录的`.m2/repository`。Maven首先查找本地仓库,若无则从远程仓库(如中央仓库)下载。中央仓库包含大量开源Java构件,可在线浏览于http://search.maven.org/。
|
5月前
|
Java Linux Maven
Maven 仓库
Maven仓库管理依赖,包括本地、中央和远程仓库。本地仓库在首次运行时创建,默认位于用户目录的`.m2/repository`。若本地缺少构件,Maven会从远程仓库下载,中央仓库是默认的远程源,包含大量开源Java构件。中央仓库无需配置,可通过HTTP访问,[search.maven.org](http://search.maven.org/#browse)可浏览其内容。
|
5月前
|
Java Maven
maven常用仓库
maven常用仓库
186 2

推荐镜像

更多
下一篇
无影云桌面