android 发布aar到私有仓库

发布aar到私有仓库大概分为两种方案:

方案一: 利用 maven 插件:

  1. 在项目根目录下新建 upload.gradle 文件:
apply plugin: 'maven'

afterEvaluate { module ->
    // 将源码打包发布
    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.srcDirs
    }

    // 将类说明文档打包发布
    tasks.withType(Javadoc) {
        // 设置编码
        options.encoding = 'UTF-8'
    }
    task androidJavadoc(type: Javadoc) {
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
        destinationDir = file("./javadoc/")
        // 忽略错误
        failOnError false
    }
    task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
        classifier = 'javadoc'
        from androidJavadoc.destinationDir
    }

    artifacts {
        archives androidSourcesJar
        archives androidJavadocJar
    }

    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: MAVEN_URL) {
                    authentication(userName: MAVEN_USER_NAME, password: MAVEN_PWD)
                }
                pom.artifactId = ARTIFACT_ID
                pom.groupId = GROUP_ID
                pom.version = android.defaultConfig.versionName
                pom.packaging = PACKAGE_TYPE
            }
            doLast {
                println "upload aar success."
            }
        }
    }
}
  1. 在项目的根目录的 gradle.properties 中添加配置项:
# 发布私有仓库的地址,我这里是本机地址
MAVEN_URL=file://localhost/e:/deploy/
# 如果私有仓库有账号,这里为账号
MAVEN_USER_NAME=admin
# 如果私有仓库有密码,这里为密码
MAVEN_PWD=123456
# 包的类型,会写到 pom 文件中
PACKAGE_TYPE=aar
# 包的分组名,和 ARTIFACT_ID 对应
GROUP_ID=com.colbert.lib
  1. 在要发布的 library 项目的目录下新建 gradle.properties 文件
# 库的名称,引用时配合GROUP_ID,implementation 'com.colbert.lib:log:1.0.0'
ARTIFACT_ID=log

4.在 library 项目的目录下的 build.gradle 文件引用改 upload.gradle 文件

apply from: '../upload.gradle'

至此,同步gradle之后,gradle 任务列表中多了个 uploadArchives 的任务,运行之后即可在仓库中看到发布的aar包。

以上是针对 library 项目中没有 flavor 的情况,但如果 library 中含有 flavor,例如:

library 项目中有以下配置:

flavorDimensions 'push'
productFlavors {
    excludePush {
        dimension 'push'
    }
    includePush {
        dimension 'push'
    }
}

运行 uploadArchives 任务会任何库都不会发布,需要加以下配置:

android {
    // 默认发布的配置,必须加
    defaultPublishConfig 'excludePushRelease'
}

加了上面的配置,你会发现可以发布了,但生成的库的 pom 没有依赖信息,所以我们要重新写一个 upload.gradle 文件,添加依赖信息。

在 library 的项目文件加下,新建 upload.gradle 文件:

afterEvaluate { project ->
    def RELEASE_BUILD_TYPE = "Release"

    // 将源码打包发布
    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.srcDirs
    }

    // 将类说明文档打包发布
    tasks.withType(Javadoc) {
        // 设置编码
        options.encoding = 'UTF-8'
    }
    task androidJavadoc(type: Javadoc) {
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
        destinationDir = file("./javadoc/")
        // 忽略错误
        failOnError false
    }
    task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
        classifier = 'javadoc'
        from androidJavadoc.destinationDir
    }

    artifacts {
        archives androidSourcesJar
        archives androidJavadocJar
    }

    uploadArchives {
        repositories {
            mavenDeployer {
                repository(url: MAVEN_URL) {
                    authentication(userName: MAVEN_USER_NAME, password: MAVEN_PWD)
                }
                android.libraryVariants.all { variant ->
                    def name = "${variant.name}"
                    addFilter(name) { artifact, file ->
                        // 只上传 release 包
                        name.contains(RELEASE_BUILD_TYPE)
                    }
                    pom(name).artifactId = archivesBaseName + "-" + flavorName
                    pom(name).version = android.defaultConfig.versionName
                    pom(name).groupId = GROUP_ID
                    pom(name).packaging = 'aar'
                    // 在 pom 文件中加入依赖
                    pom(name).withXml {
                        def root = asNode()
                        def dependenciesNode = root["dependencies"][0] ?: root.appendNode("dependencies")
                        def addDependency = {
                            if (it.group == null || it.version == null || it.name == null || it.name == "unspecified") {
                                // 忽略
                                return
                            }
                            def dependencyNode = dependenciesNode.appendNode('dependency')
                            dependencyNode.appendNode('groupId', it.group)
                            dependencyNode.appendNode('artifactId', it.name)
                            dependencyNode.appendNode('version', it.version)
                            if (it.hasProperty('optional') && it.optional) {
                                dependencyNode.appendNode('optional', 'true')
                            }
                            if (!it.transitive) {
                                def exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
                                exclusionNode.appendNode('groupId', '*')
                                exclusionNode.appendNode('artifactId', '*')
                            } else if (!it.properties.excludeRules.empty) {
                                def exclusionsNode = dependencyNode.appendNode('exclusions')
                                it.properties.excludeRules.each { rule ->
                                    def exclusionNode = exclusionsNode.appendNode('exclusion')
                                    exclusionNode.appendNode('groupId', rule.group ?: '*')
                                    exclusionNode.appendNode('artifactId', rule.module ?: '*')
                                }
                            }
                        }
                        configurations.api.allDependencies.each addDependency
                        configurations.implementation.allDependencies.each addDependency
                        configurations.compile.allDependencies.each addDependency
                        if (!flavorName.isEmpty()) {
                            def flavorNameLower = flavorName.toLowerCase()
                            android.productFlavors.each {
                                def flavor = it.name
                                if (flavorNameLower.contains(flavor.toLowerCase())) {
                                    configurations["${flavor}Implementation"].allDependencies.each addDependency
                                    configurations["${flavor}Api"].allDependencies.each addDependency
                                    configurations["${flavor}Compile"].allDependencies.each addDependency
                                }
                            }
                            configurations["${name}Implementation"].allDependencies.each addDependency
                            configurations["${name}Api"].allDependencies.each addDependency
                            configurations["${name}Compile"].allDependencies.each addDependency
                            configurations["${flavorName}Implementation"].allDependencies.each addDependency
                            configurations["${flavorName}Api"].allDependencies.each addDependency
                            configurations["${flavorName}Compile"].allDependencies.each addDependency
                        }
                    }
                }
            }
            doLast {
                println "upload aar success."
            }
        }
    }
}

在 library 中引用这个文件即可:

apply from: './upload.gradle'

这时在运行 uploadArchives 任务即可成功发布。

方案二:利用 maven-publish 插件

这种方式需要注意:
不会自动追加依赖到pom文件中,需要像上面一样,将依赖文件加进入

apply plugin: 'maven-publish'
afterEvaluate { module ->

    // 将源码打包发布
    task androidSourcesJar(type: Jar) {
        classifier = 'sources'
        from android.sourceSets.main.java.srcDirs
    }

    // 将文档打包发布
    tasks.withType(Javadoc) {
        // 设置编码
        options.encoding = 'UTF-8'
    }
    task androidJavadoc(type: Javadoc) {
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
        destinationDir = file("./javadoc/")
        // 忽略错误
        failOnError false
    }
    task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
        classifier = 'javadoc'
        from androidJavadoc.destinationDir
    }

    artifacts {
        archives androidSourcesJar
        archives androidJavadocJar
    }
    publishing {
        publications {
            maven(MavenPublication) {
                groupId GROUP_ID
                artifactId ARTIFACT_ID
                version android.defaultConfig.versionName
                artifact bundleRelease
                artifact androidJavadocJar
                artifact androidSourcesJar
                // 在 pom 文件中加入依赖
                pom(name).withXml {
                    def root = asNode()
                    def dependenciesNode = root["dependencies"][0] ?: root.appendNode("dependencies")
                    def addDependency = {
                        if (it.group == null || it.version == null || it.name == null || it.name == "unspecified") {
                            // 忽略
                            return
                        }
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                        if (it.hasProperty('optional') && it.optional) {
                            dependencyNode.appendNode('optional', 'true')
                        }
                        if (!it.transitive) {
                            def exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
                            exclusionNode.appendNode('groupId', '*')
                            exclusionNode.appendNode('artifactId', '*')
                        } else if (!it.properties.excludeRules.empty) {
                            def exclusionsNode = dependencyNode.appendNode('exclusions')
                            it.properties.excludeRules.each { rule ->
                                def exclusionNode = exclusionsNode.appendNode('exclusion')
                                exclusionNode.appendNode('groupId', rule.group ?: '*')
                                exclusionNode.appendNode('artifactId', rule.module ?: '*')
                            }
                        }
                    }
                    configurations.api.allDependencies.each addDependency
                    configurations.implementation.allDependencies.each addDependency
                    configurations.compile.allDependencies.each addDependency
                    if (!flavorName.isEmpty()) {
                        def flavorNameLower = flavorName.toLowerCase()
                        android.productFlavors.each {
                            def flavor = it.name
                            if (flavorNameLower.contains(flavor.toLowerCase())) {
                                configurations["${flavor}Implementation"].allDependencies.each addDependency
                                configurations["${flavor}Api"].allDependencies.each addDependency
                                configurations["${flavor}Compile"].allDependencies.each addDependency
                            }
                        }
                        configurations["${name}Implementation"].allDependencies.each addDependency
                        configurations["${name}Api"].allDependencies.each addDependency
                        configurations["${name}Compile"].allDependencies.each addDependency
                        configurations["${flavorName}Implementation"].allDependencies.each addDependency
                        configurations["${flavorName}Api"].allDependencies.each addDependency
                        configurations["${flavorName}Compile"].allDependencies.each addDependency
                    }
                }
            }
        }
        repositories {
            maven {
                // 本地文件路径改成 "file://e:/deploy"
                url = MAVEN_URL 
                // 本地文件不支持 credentials 这种认证,请注释掉
                credentials {
                    username MAVEN_USER_NAME
                    password MAVEN_PWD
                }
            }
        }
    }
}

在右边的 gradle 任务栏中多了个 publishing 文件夹, 运行里面 publishMavenPublicationToMavenRepository 的任务即可。

这里需要注意:
如果你发布的library库引用了别的子项目,建议将子项目单独配置发布,在library中都引用maven格式的地址。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341