// 打印所有组件名components.all {println "it: " + it.name}
/*** 打包源码*/task sourcesJar(type: Jar) {archiveClassifier = "sources"from android.sourceSets.main.java.srcDirs}
1/maven-publish
注意事项:因为组件仅在 afterEvaluate 阶段创建,所以必须使用 afterEvaluate() 生命周期方法配置发布
release 正式包
apply plugin: 'maven-publish'afterEvaluate {publishing {publications {release(MavenPublication) {from components.releasegroupId = GROUP_IDartifactId = ARTIFACT_IDversion = VERSION}}}}
debug 测试包
apply plugin: 'maven-publish'afterEvaluate {publishing {publications {debug(MavenPublication) {from components.debuggroupId = GROUP_IDartifactId = ARTIFACT_IDversion = VERSION}}}}
allVariants 全部版本包
apply plugin: 'maven-publish'afterEvaluate {publishing {publications {android.libraryVariants.all { variant ->"${variant.name}Aar"(MavenPublication) {from components.findByName("${variant.name}")groupId = GROUP_IDartifactId = ARTIFACT_IDversion = VERSION + "-${variant.name}"}}}}}
moreMaven 多 maven
注意事项:默认包含本地 maven(mavenLocal() | ~/.me/repository)
apply plugin: 'maven-publish'afterEvaluate {publishing {publications {......}repositories {maven {// 第二个必须显示指定 namename = "MavenOfProject"url = uri("$rootDir/repo/")}}}}
上述代码可以直接添加到 lib 项目的 build.gradle 文件底部, 也可以独立到一个 upload.gradle 文件里在 lib 项目的 build.gradle 文件底部引入
引入方式:
// maven库配置ext {USERNAME = "xxx"PASSWORD = "xxx"GROUP_ID = "com.xxx.xxx"ARTIFACT_ID = "xxx"VERSION = "1.0.0"}apply from: "$rootDir/upload.gradle"
Sync Now 项目编译完成后就可以看到下图所示:
- publish 全部打包上传 (所有variants,所有 maven,不包含本地)
- publishAll…ToXXXRepository 打包指定 maven 的所有 variants
- publishDebug… 上传 debug 版本
- publishRelease… 上传 release 版本
- publishToMavenLocal 上传到本地Maven缓存中(通常为$ USER_HOME / .m2 / repository)
2/maven (已过时)
2.1/关键词说明
2.1.1/defaultPublishConfig
android.defaultPublishConfig控制项目默认发布版本, 默认值是release2.1.2/打包 aar
maven 的默认上传任务根据android.defaultPublishConfig的值决定, 默认情况下是 bundleReleaseAar, 也就是上传 release 版本的 aar 包
当然 maven 上传的 aar 是可以修改的, 前提是需要先打包指定的 aar, 然后添加到artifacts中2.1.3/包含打包的任务
包含打包的任务有: bundleXXXAar和 assembleXXX 系列, 打包所有版本就只有assemble任务可以做到
如果项目设置了productFlavors, 在打包发布指定flavors + debug/release版本时就需要依赖bundle + Flavor + Debug/ReleaseAar也可以是assemble + Flavor + Debug/Release2.1.4/artifacts
artifacts 可以理解为要打包的文件, 默认情况下包含xxx.aarxxx 为项目名, aar 版本为默认版本
artifacts 的配置是增量模式, 可以同时定义在所有任务外部和任务内部, 在任务外部就是全局配置, 发布时合并外部和内部的配置
当发布指定版本 aar 的时候先需要添加到 artifacts 中, 如果定义了多个发布 task 里面都添加了指定版本的 aar 可能会出现 aar 重复或找不到的问题, 所以 task 内部的 aar 最好用 doLast{} 进行隔离, 等到 task 执行的时候再添加 ```groovy artifacts { archives sourcesJar }
// or task xxx(type: Upload) { … repositories { maven… { … doLast { artifacts { archives sourcesJar archives file: file(“build/outputs/aar/xxx.aar”) // 也可以通过 task 来获取 aar archives bundleXXXAar } } … } } }
<a name="ZjUP4"></a>#### 2.1.5/pom`.pom` 文件是项目的配置文件包含项目信息和依赖配置信息, 有时候在发布指定版本的 aar 时需要定制 pom 文件里的依赖配置信息```groovy// 默认版本, 默认版本不支持 withXml 操作pom.groupId = GROUP_IDpom.artifactId = ARTIFACT_IDpom.version = VERSION + "-SNAPSHOT"// 指定版本 variantNamepom(variantName).groupId = GROUP_IDpom(variantName).artifactId = ARTIFACT_IDpom(variantName).version = VERSION + "-SNAPSHOT"pom(variantName).withXml {...}
pom.withXml 就是配置 .pom 文件
// variantName 为指定版本, 可不设置(默认), 发布指定版本时需要设置pom(variantName).withXml {// 添加依赖节点的闭包def addNode = { rootNode, list ->list.each {if (null != it.group) {def dependency = rootNode.appendNode('dependency')dependency.appendNode('groupId', it.group)dependency.appendNode('artifactId', it.name)dependency.appendNode('version', it.version)dependency.appendNode('scope', 'compile')}}}// 创建根节点def rootNode = asNode().appendNode('dependencies')// 查询所有 implementation, api, compile 依赖def implementations = configurations.findByName("implementation").allDependencies// 查询所有 variantNameImplementation, api, compile 依赖def variantNameImplementations = configurations.findByName("${variantName}Implementation").allDependencies// 遍历添加依赖节点addNode(rootNode, implementations)addNode(rootNode, variantNameImplementations)}
2.1.6/mavenInstaller/mavenDeployer
mavenInstaller
发布到本地默认 maven 库, 通过 mavenLocal() 库引用, 无需设置 URL
task xxx(type: Upload) {...repositories {mavenInstaller {...}}}
使用方式:
第一种方式: 在根目录的 build.gradle 添加配置
...allprojects {repositories {...mavenLocal()...}}...
第二种方式: 在 module 的 build.gradle 添加配置
...android {...repositories {...mavenLocal()...}...}...
mavenDeployer
发布到指定 maven 库, 通过 URL 指定 maven 地址
// 以项目根目录下的 /repo/release 目录作为 maven 仓库def URL_LOCAL = uri("$rootDir/repo/release")// 以私服作为 maven 仓库def URL_REMOTE = "http://xxx/repo/release"task xxx(type: Upload) {...repositories {mavenDeployer {...repository(url: URL_REMOTE/URL_LOCAL) {// 设置用户名, 密码, 没有可以不添加authentication(userName: USERNAME, password: PASSWORD)}...}}}
使用方式与 mavenInstaller 类似, mavenLocal() 修改为 maven { url: xxx }
maven {url 'http://x.x.x.x:8081/repository/'credentials {username 'xxx'password 'xxx'}}
2.2/非默认版本/多版本
有时会因为业务的需要分出多种版本, 在发布其他非默认版本时需要做一些配置
2.2.1/发布指定版本
task xxx(type: Upload) {...repositories {maven...... {...def variantName = "debug"def variantBaseName = "debug"def buildTypeName = "debug"def fileName = "${project.name}-${variantBaseName}.aar"doLast {artifacts {archives bundleDebugAar}}addFilter(variantName) { artifact, file ->def artifactName = artifact.namedef artifactType = artifact.typeif ("aar" == artifactType) {return artifactName == fileName} else {true}}pom(variantName).groupId = GROUP_IDpom(variantName).artifactId = ARTIFACT_ID + "-" + variantBaseNamepom(variantName).version = VERSIONpom(variantName).withXml {// 添加依赖包节点的闭包def addNode = { rootNode, list ->list.each {if (null != it.group) {def dependency = rootNode.appendNode('dependency')dependency.appendNode('groupId', it.group)dependency.appendNode('artifactId', it.name)dependency.appendNode('version', it.version)dependency.appendNode('scope', 'compile')}}}// 创建根节点def rootNode = asNode().appendNode('dependencies')def implementations = configurations.findByName("implementation").allDependenciesdef variantImplementations = configurations.findByName("${buildTypeName}Implementation").allDependenciesaddNode(rootNode, implementations)addNode(rootNode, variantImplementations)}}}}
2.2.2/发布全部版本
发布全部版本原理同单个版本基本一致, 主要区别在于通过读取版本配置信息进行遍历发布
// 创建并发布所有变体task xxx(type: Upload) {dependsOn "assemble"...repositories {maven...... {...android.libraryVariants.all { variant ->def variantName = variant.namedef variantBaseName = variant.baseNamedef buildTypeName = variant.buildType.namedef fileName = "${project.name}-${variantBaseName}.aar"doLast {artifacts {archives file: file("build/outputs/aar/${fileName}")}}addFilter(variantName) { artifact, file ->def artifactName = artifact.namedef artifactType = artifact.typeif ("aar" == artifactType) {return artifactName == fileName} else {true}}pom(variantName).groupId = GROUP_IDpom(variantName).artifactId = ARTIFACT_ID + "-" + variantBaseNamepom(variantName).version = VERSIONpom(variantName).withXml {// 添加依赖包节点的闭包def addNode = { rootNode, list ->list.each {if (null != it.group) {def dependency = rootNode.appendNode('dependency')dependency.appendNode('groupId', it.group)dependency.appendNode('artifactId', it.name)dependency.appendNode('version', it.version)dependency.appendNode('scope', 'compile')}}}// 创建根节点def rootNode = asNode().appendNode('dependencies')def implementations = configurations.findByName("implementation").allDependenciesdef variantImplementations = configurations.findByName("${buildTypeName}Implementation").allDependenciesaddNode(rootNode, implementations)addNode(rootNode, variantImplementations)}}}}}
2.2.3/完整示例代码
apply plugin: 'maven'// 打包源码task sourcesJar(type: Jar) {group = 'uploadMaven'archiveClassifier = "sources"from android.sourceSets.main.java.srcDirs}// 压缩生成归档文件task packZip(type: Zip) {group = 'uploadMaven'archiveBaseName = project.namearchiveAppendix = VERSIONarchiveClassifier = "all"archiveExtension = "zip"// 打包根路径from project.projectDir.absolutePath// 输出路径// destinationDir = project.projectDir.absoluteFileexclude '**.zip'exclude '**.iml'exclude '**/**.iml'exclude 'build/**'exclude '.idea/**'exclude '.gradle/**'exclude 'gradle/**'exclude '**/build/**'exclude 'repo/**'}artifacts {archives sourcesJararchives packZip}def URL_LOCAL = uri("$rootDir/repo/")def URL_REMOTE = "http://x.x.x.x:8081/repository/"task upload2Local(type: Upload) {group = "uploadMaven"configuration = configurations.archivesuploadDescriptor = truerepositories {mavenInstaller {pom.groupId = GROUP_IDpom.artifactId = ARTIFACT_IDpom.version = VERSION}}}task uploadDebug2Project(type: Upload) {dependsOn "bundleDebugAar"group = "uploadMaven"configuration = configurations.archivesuploadDescriptor = truerepositories {mavenDeployer {repository(url: URL_LOCAL)def variantName = "debug"def variantBaseName = "${project.name}-${variantName}"def fileName = "${project.buildDir}/outputs/aar/${variantBaseName}.aar"artifacts {archives file: file(fileName)}addFilter(variantName) { artifact, file ->def artifactName = artifact.namedef artifactType = artifact.typeif ("aar" == artifactType) {return variantBaseName == artifactName} else {true}}pom(variantName).groupId = GROUP_IDpom(variantName).artifactId = ARTIFACT_ID + "-" + variantNamepom(variantName).version = VERSIONpom(variantName).withXml {// 添加依赖包节点的闭包def addNode = { rootNode, list ->list.each {if (null != it.group) {def dependency = rootNode.appendNode('dependency')dependency.appendNode('groupId', it.group)dependency.appendNode('artifactId', it.name)dependency.appendNode('version', it.version)dependency.appendNode('scope', 'compile')}}}// 创建根节点def rootNode = asNode().appendNode('dependencies')def implementations = configurations.findByName("implementation").allDependenciesdef variantImplementations = configurations.findByName("${variantName}Implementation").allDependenciesaddNode(rootNode, implementations)addNode(rootNode, variantImplementations)}}}}task uploadAll2Remote(type: Upload) {dependsOn "assemble"group = "uploadMaven"configuration = configurations.archivesuploadDescriptor = truerepositories {mavenDeployer {// 无需密码repository(url: URL_LOCAL)// 需要密码repository(url: URL_LOCAL) {authentication(userName: "xxx", password: "xxx")}android.libraryVariants.all { variant ->def variantName = variant.namedef variantBaseName = "${project.name}-${variantName}"def fileName = "${project.buildDir}/outputs/aar/${variantBaseName}.aar"artifacts {archives file: file(fileName)}addFilter(variantName) { artifact, file ->def artifactName = artifact.namedef artifactType = artifact.typeif ("aar" == artifactType) {return variantBaseName == artifactName} else {true}}pom(variantName).groupId = GROUP_IDpom(variantName).artifactId = ARTIFACT_ID + "-" + variantNamepom(variantName).version = VERSIONpom(variantName).withXml {// 添加依赖包节点的闭包def addNode = { rootNode, list ->list.each {if (null != it.group) {def dependency = rootNode.appendNode('dependency')dependency.appendNode('groupId', it.group)dependency.appendNode('artifactId', it.name)dependency.appendNode('version', it.version)dependency.appendNode('scope', 'compile')}}}// 创建根节点def rootNode = asNode().appendNode('dependencies')def implementations = configurations.findByName("implementation").allDependenciesdef variantImplementations = configurations.findByName("${variantName}Implementation").allDependenciesaddNode(rootNode, implementations)addNode(rootNode, variantImplementations)}}}}}
2.3/注意事项
// 发布脚本用户名密码配置repositories {mavenDeployer {repository(url: URL_LOCAL) {authentication(userName: "xxx", password: "xxx")}}}// 项目配置脚本用户名密码配置allprojects {repositories {maven {credentials {username 'xxx'password 'xxx'}url URL_LOCAL}}}
3/不同阶段的命名方案
- 规划:版本名 + “-SNAPSHOT”
- 测试:版本名 + “-debug(1..n)”
- 发布:版本名
测试阶段,为了更快的编译速度可以发布到本地默认的 maven 库。测试完成后再发布到 maven 私服
4/其它
task pVariant() {doLast {android.libraryVariants.all { variant ->println ">>>>>>>>> name: ${variant.name}"println ">>>>>>>>> baseName: ${variant.baseName}"println ">>>>>>>>> flavorName: ${variant.flavorName}"println ">>>>>>>>> buildTypeName: ${variant.buildType.name}"}}}
