1. // 打印所有组件名
  2. components.all {
  3. println "it: " + it.name
  4. }
  1. /**
  2. * 打包源码
  3. */
  4. task sourcesJar(type: Jar) {
  5. archiveClassifier = "sources"
  6. from android.sourceSets.main.java.srcDirs
  7. }

1/maven-publish

注意事项:因为组件仅在 afterEvaluate 阶段创建,所以必须使用 afterEvaluate() 生命周期方法配置发布

release 正式包

  1. apply plugin: 'maven-publish'
  2. afterEvaluate {
  3. publishing {
  4. publications {
  5. release(MavenPublication) {
  6. from components.release
  7. groupId = GROUP_ID
  8. artifactId = ARTIFACT_ID
  9. version = VERSION
  10. }
  11. }
  12. }
  13. }

debug 测试包

  1. apply plugin: 'maven-publish'
  2. afterEvaluate {
  3. publishing {
  4. publications {
  5. debug(MavenPublication) {
  6. from components.debug
  7. groupId = GROUP_ID
  8. artifactId = ARTIFACT_ID
  9. version = VERSION
  10. }
  11. }
  12. }
  13. }

allVariants 全部版本包

  1. apply plugin: 'maven-publish'
  2. afterEvaluate {
  3. publishing {
  4. publications {
  5. android.libraryVariants.all { variant ->
  6. "${variant.name}Aar"(MavenPublication) {
  7. from components.findByName("${variant.name}")
  8. groupId = GROUP_ID
  9. artifactId = ARTIFACT_ID
  10. version = VERSION + "-${variant.name}"
  11. }
  12. }
  13. }
  14. }
  15. }

moreMaven 多 maven

注意事项:默认包含本地 maven(mavenLocal() | ~/.me/repository)

  1. apply plugin: 'maven-publish'
  2. afterEvaluate {
  3. publishing {
  4. publications {
  5. ......
  6. }
  7. repositories {
  8. maven {
  9. // 第二个必须显示指定 name
  10. name = "MavenOfProject"
  11. url = uri("$rootDir/repo/")
  12. }
  13. }
  14. }
  15. }

上述代码可以直接添加到 lib 项目的 build.gradle 文件底部, 也可以独立到一个 upload.gradle 文件里在 lib 项目的 build.gradle 文件底部引入
引入方式:

  1. // maven库配置
  2. ext {
  3. USERNAME = "xxx"
  4. PASSWORD = "xxx"
  5. GROUP_ID = "com.xxx.xxx"
  6. ARTIFACT_ID = "xxx"
  7. VERSION = "1.0.0"
  8. }
  9. apply from: "$rootDir/upload.gradle"

Sync Now 项目编译完成后就可以看到下图所示:
image.png

  • 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 控制项目默认发布版本, 默认值是 release

    2.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/Release

    2.1.4/artifacts

    artifacts 可以理解为要打包的文件, 默认情况下包含 xxx.aar xxx 为项目名, 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 } } … } } }

  1. <a name="ZjUP4"></a>
  2. #### 2.1.5/pom
  3. `.pom` 文件是项目的配置文件包含项目信息和依赖配置信息, 有时候在发布指定版本的 aar 时需要定制 pom 文件里的依赖配置信息
  4. ```groovy
  5. // 默认版本, 默认版本不支持 withXml 操作
  6. pom.groupId = GROUP_ID
  7. pom.artifactId = ARTIFACT_ID
  8. pom.version = VERSION + "-SNAPSHOT"
  9. // 指定版本 variantName
  10. pom(variantName).groupId = GROUP_ID
  11. pom(variantName).artifactId = ARTIFACT_ID
  12. pom(variantName).version = VERSION + "-SNAPSHOT"
  13. pom(variantName).withXml {
  14. ...
  15. }

pom.withXml 就是配置 .pom 文件

  1. // variantName 为指定版本, 可不设置(默认), 发布指定版本时需要设置
  2. pom(variantName).withXml {
  3. // 添加依赖节点的闭包
  4. def addNode = { rootNode, list ->
  5. list.each {
  6. if (null != it.group) {
  7. def dependency = rootNode.appendNode('dependency')
  8. dependency.appendNode('groupId', it.group)
  9. dependency.appendNode('artifactId', it.name)
  10. dependency.appendNode('version', it.version)
  11. dependency.appendNode('scope', 'compile')
  12. }
  13. }
  14. }
  15. // 创建根节点
  16. def rootNode = asNode().appendNode('dependencies')
  17. // 查询所有 implementation, api, compile 依赖
  18. def implementations = configurations.findByName("implementation").allDependencies
  19. // 查询所有 variantNameImplementation, api, compile 依赖
  20. def variantNameImplementations = configurations.findByName("${variantName}Implementation").allDependencies
  21. // 遍历添加依赖节点
  22. addNode(rootNode, implementations)
  23. addNode(rootNode, variantNameImplementations)
  24. }

2.1.6/mavenInstaller/mavenDeployer

mavenInstaller

发布到本地默认 maven 库, 通过 mavenLocal() 库引用, 无需设置 URL

  1. task xxx(type: Upload) {
  2. ...
  3. repositories {
  4. mavenInstaller {
  5. ...
  6. }
  7. }
  8. }

使用方式:

第一种方式: 在根目录的 build.gradle 添加配置
  1. ...
  2. allprojects {
  3. repositories {
  4. ...
  5. mavenLocal()
  6. ...
  7. }
  8. }
  9. ...

第二种方式: 在 module 的 build.gradle 添加配置
  1. ...
  2. android {
  3. ...
  4. repositories {
  5. ...
  6. mavenLocal()
  7. ...
  8. }
  9. ...
  10. }
  11. ...

mavenDeployer

发布到指定 maven 库, 通过 URL 指定 maven 地址

  1. // 以项目根目录下的 /repo/release 目录作为 maven 仓库
  2. def URL_LOCAL = uri("$rootDir/repo/release")
  3. // 以私服作为 maven 仓库
  4. def URL_REMOTE = "http://xxx/repo/release"
  5. task xxx(type: Upload) {
  6. ...
  7. repositories {
  8. mavenDeployer {
  9. ...
  10. repository(url: URL_REMOTE/URL_LOCAL) {
  11. // 设置用户名, 密码, 没有可以不添加
  12. authentication(userName: USERNAME, password: PASSWORD)
  13. }
  14. ...
  15. }
  16. }
  17. }

使用方式与 mavenInstaller 类似, mavenLocal() 修改为 maven { url: xxx }
  1. maven {
  2. url 'http://x.x.x.x:8081/repository/'
  3. credentials {
  4. username 'xxx'
  5. password 'xxx'
  6. }
  7. }

2.2/非默认版本/多版本

有时会因为业务的需要分出多种版本, 在发布其他非默认版本时需要做一些配置

2.2.1/发布指定版本

  1. task xxx(type: Upload) {
  2. ...
  3. repositories {
  4. maven...... {
  5. ...
  6. def variantName = "debug"
  7. def variantBaseName = "debug"
  8. def buildTypeName = "debug"
  9. def fileName = "${project.name}-${variantBaseName}.aar"
  10. doLast {
  11. artifacts {
  12. archives bundleDebugAar
  13. }
  14. }
  15. addFilter(variantName) { artifact, file ->
  16. def artifactName = artifact.name
  17. def artifactType = artifact.type
  18. if ("aar" == artifactType) {
  19. return artifactName == fileName
  20. } else {
  21. true
  22. }
  23. }
  24. pom(variantName).groupId = GROUP_ID
  25. pom(variantName).artifactId = ARTIFACT_ID + "-" + variantBaseName
  26. pom(variantName).version = VERSION
  27. pom(variantName).withXml {
  28. // 添加依赖包节点的闭包
  29. def addNode = { rootNode, list ->
  30. list.each {
  31. if (null != it.group) {
  32. def dependency = rootNode.appendNode('dependency')
  33. dependency.appendNode('groupId', it.group)
  34. dependency.appendNode('artifactId', it.name)
  35. dependency.appendNode('version', it.version)
  36. dependency.appendNode('scope', 'compile')
  37. }
  38. }
  39. }
  40. // 创建根节点
  41. def rootNode = asNode().appendNode('dependencies')
  42. def implementations = configurations.findByName("implementation").allDependencies
  43. def variantImplementations = configurations.findByName("${buildTypeName}Implementation").allDependencies
  44. addNode(rootNode, implementations)
  45. addNode(rootNode, variantImplementations)
  46. }
  47. }
  48. }
  49. }

2.2.2/发布全部版本

发布全部版本原理同单个版本基本一致, 主要区别在于通过读取版本配置信息进行遍历发布

  1. // 创建并发布所有变体
  2. task xxx(type: Upload) {
  3. dependsOn "assemble"
  4. ...
  5. repositories {
  6. maven...... {
  7. ...
  8. android.libraryVariants.all { variant ->
  9. def variantName = variant.name
  10. def variantBaseName = variant.baseName
  11. def buildTypeName = variant.buildType.name
  12. def fileName = "${project.name}-${variantBaseName}.aar"
  13. doLast {
  14. artifacts {
  15. archives file: file("build/outputs/aar/${fileName}")
  16. }
  17. }
  18. addFilter(variantName) { artifact, file ->
  19. def artifactName = artifact.name
  20. def artifactType = artifact.type
  21. if ("aar" == artifactType) {
  22. return artifactName == fileName
  23. } else {
  24. true
  25. }
  26. }
  27. pom(variantName).groupId = GROUP_ID
  28. pom(variantName).artifactId = ARTIFACT_ID + "-" + variantBaseName
  29. pom(variantName).version = VERSION
  30. pom(variantName).withXml {
  31. // 添加依赖包节点的闭包
  32. def addNode = { rootNode, list ->
  33. list.each {
  34. if (null != it.group) {
  35. def dependency = rootNode.appendNode('dependency')
  36. dependency.appendNode('groupId', it.group)
  37. dependency.appendNode('artifactId', it.name)
  38. dependency.appendNode('version', it.version)
  39. dependency.appendNode('scope', 'compile')
  40. }
  41. }
  42. }
  43. // 创建根节点
  44. def rootNode = asNode().appendNode('dependencies')
  45. def implementations = configurations.findByName("implementation").allDependencies
  46. def variantImplementations = configurations.findByName("${buildTypeName}Implementation").allDependencies
  47. addNode(rootNode, implementations)
  48. addNode(rootNode, variantImplementations)
  49. }
  50. }
  51. }
  52. }
  53. }

2.2.3/完整示例代码

  1. apply plugin: 'maven'
  2. // 打包源码
  3. task sourcesJar(type: Jar) {
  4. group = 'uploadMaven'
  5. archiveClassifier = "sources"
  6. from android.sourceSets.main.java.srcDirs
  7. }
  8. // 压缩生成归档文件
  9. task packZip(type: Zip) {
  10. group = 'uploadMaven'
  11. archiveBaseName = project.name
  12. archiveAppendix = VERSION
  13. archiveClassifier = "all"
  14. archiveExtension = "zip"
  15. // 打包根路径
  16. from project.projectDir.absolutePath
  17. // 输出路径
  18. // destinationDir = project.projectDir.absoluteFile
  19. exclude '**.zip'
  20. exclude '**.iml'
  21. exclude '**/**.iml'
  22. exclude 'build/**'
  23. exclude '.idea/**'
  24. exclude '.gradle/**'
  25. exclude 'gradle/**'
  26. exclude '**/build/**'
  27. exclude 'repo/**'
  28. }
  29. artifacts {
  30. archives sourcesJar
  31. archives packZip
  32. }
  33. def URL_LOCAL = uri("$rootDir/repo/")
  34. def URL_REMOTE = "http://x.x.x.x:8081/repository/"
  35. task upload2Local(type: Upload) {
  36. group = "uploadMaven"
  37. configuration = configurations.archives
  38. uploadDescriptor = true
  39. repositories {
  40. mavenInstaller {
  41. pom.groupId = GROUP_ID
  42. pom.artifactId = ARTIFACT_ID
  43. pom.version = VERSION
  44. }
  45. }
  46. }
  47. task uploadDebug2Project(type: Upload) {
  48. dependsOn "bundleDebugAar"
  49. group = "uploadMaven"
  50. configuration = configurations.archives
  51. uploadDescriptor = true
  52. repositories {
  53. mavenDeployer {
  54. repository(url: URL_LOCAL)
  55. def variantName = "debug"
  56. def variantBaseName = "${project.name}-${variantName}"
  57. def fileName = "${project.buildDir}/outputs/aar/${variantBaseName}.aar"
  58. artifacts {
  59. archives file: file(fileName)
  60. }
  61. addFilter(variantName) { artifact, file ->
  62. def artifactName = artifact.name
  63. def artifactType = artifact.type
  64. if ("aar" == artifactType) {
  65. return variantBaseName == artifactName
  66. } else {
  67. true
  68. }
  69. }
  70. pom(variantName).groupId = GROUP_ID
  71. pom(variantName).artifactId = ARTIFACT_ID + "-" + variantName
  72. pom(variantName).version = VERSION
  73. pom(variantName).withXml {
  74. // 添加依赖包节点的闭包
  75. def addNode = { rootNode, list ->
  76. list.each {
  77. if (null != it.group) {
  78. def dependency = rootNode.appendNode('dependency')
  79. dependency.appendNode('groupId', it.group)
  80. dependency.appendNode('artifactId', it.name)
  81. dependency.appendNode('version', it.version)
  82. dependency.appendNode('scope', 'compile')
  83. }
  84. }
  85. }
  86. // 创建根节点
  87. def rootNode = asNode().appendNode('dependencies')
  88. def implementations = configurations.findByName("implementation").allDependencies
  89. def variantImplementations = configurations.findByName("${variantName}Implementation").allDependencies
  90. addNode(rootNode, implementations)
  91. addNode(rootNode, variantImplementations)
  92. }
  93. }
  94. }
  95. }
  96. task uploadAll2Remote(type: Upload) {
  97. dependsOn "assemble"
  98. group = "uploadMaven"
  99. configuration = configurations.archives
  100. uploadDescriptor = true
  101. repositories {
  102. mavenDeployer {
  103. // 无需密码
  104. repository(url: URL_LOCAL)
  105. // 需要密码
  106. repository(url: URL_LOCAL) {
  107. authentication(userName: "xxx", password: "xxx")
  108. }
  109. android.libraryVariants.all { variant ->
  110. def variantName = variant.name
  111. def variantBaseName = "${project.name}-${variantName}"
  112. def fileName = "${project.buildDir}/outputs/aar/${variantBaseName}.aar"
  113. artifacts {
  114. archives file: file(fileName)
  115. }
  116. addFilter(variantName) { artifact, file ->
  117. def artifactName = artifact.name
  118. def artifactType = artifact.type
  119. if ("aar" == artifactType) {
  120. return variantBaseName == artifactName
  121. } else {
  122. true
  123. }
  124. }
  125. pom(variantName).groupId = GROUP_ID
  126. pom(variantName).artifactId = ARTIFACT_ID + "-" + variantName
  127. pom(variantName).version = VERSION
  128. pom(variantName).withXml {
  129. // 添加依赖包节点的闭包
  130. def addNode = { rootNode, list ->
  131. list.each {
  132. if (null != it.group) {
  133. def dependency = rootNode.appendNode('dependency')
  134. dependency.appendNode('groupId', it.group)
  135. dependency.appendNode('artifactId', it.name)
  136. dependency.appendNode('version', it.version)
  137. dependency.appendNode('scope', 'compile')
  138. }
  139. }
  140. }
  141. // 创建根节点
  142. def rootNode = asNode().appendNode('dependencies')
  143. def implementations = configurations.findByName("implementation").allDependencies
  144. def variantImplementations = configurations.findByName("${variantName}Implementation").allDependencies
  145. addNode(rootNode, implementations)
  146. addNode(rootNode, variantImplementations)
  147. }
  148. }
  149. }
  150. }
  151. }

2.3/注意事项

  1. // 发布脚本用户名密码配置
  2. repositories {
  3. mavenDeployer {
  4. repository(url: URL_LOCAL) {
  5. authentication(userName: "xxx", password: "xxx")
  6. }
  7. }
  8. }
  9. // 项目配置脚本用户名密码配置
  10. allprojects {
  11. repositories {
  12. maven {
  13. credentials {
  14. username 'xxx'
  15. password 'xxx'
  16. }
  17. url URL_LOCAL
  18. }
  19. }
  20. }

3/不同阶段的命名方案

  • 规划:版本名 + “-SNAPSHOT”
  • 测试:版本名 + “-debug(1..n)”
  • 发布:版本名

测试阶段,为了更快的编译速度可以发布到本地默认的 maven 库。测试完成后再发布到 maven 私服

4/其它

  1. task pVariant() {
  2. doLast {
  3. android.libraryVariants.all { variant ->
  4. println ">>>>>>>>> name: ${variant.name}"
  5. println ">>>>>>>>> baseName: ${variant.baseName}"
  6. println ">>>>>>>>> flavorName: ${variant.flavorName}"
  7. println ">>>>>>>>> buildTypeName: ${variant.buildType.name}"
  8. }
  9. }
  10. }

参考链接