使用 Gradle Kotlin DSL 将 Android aar 发布到 Maven Repository - JFrog 的几点经验

2,444 阅读2分钟

近期正在着手将一些项目中共用组件抽离到底层,封装为组件,发布到公司内网 Jrog 搭建的 Maven 库。并且想要尝试使用 Gradle Kotlin DSL 替代 Gradle Groovy 来构建项目,遇到了一些坑,特此记录分享以下。

开发环境

  • Android Studio Giraffe | 2022.3.1 RC 1
  • JDK 17
  • AGP 8.0.2

Groovy 迁移到 Kotlin DSL

可以参考以下霍老师的这篇文章 快速迁移 Gradle 脚本至 KTS | Benny Huo

依赖 Jrog 插件

Gradle - Plugin: com.jfrog.artifactory

项目根目录

//依赖 jrog 插件
plugins {
  //...省略其他插件
  id("com.jfrog.artifactory") version "4.29.1"
}

Module 目录

plugins {
	//...省略其他插件
	id("com.jfrog.artifactory")
	id("maven-publish")
}

修改输出的 AAR 文件名


android{
    //...
    defaultConfig {
        minSdk = 21
        version = 1
    }
	//以下 moduleCommonArtifactId 为自定义名称,version 为 defalut 的 version 值,当然怎么命名自己决定
    libraryVariants.configureEach {
            outputs.configureEach {
                val output = this as BaseVariantOutputImpl
                if (output.outputFileName.endsWith(".aar")) {
                    output.outputFileName = "${moduleCommonArtifactId}_${version}.aar"
                }
            }
        }
    //...
}

打包源码中的 Java 和 Kotlin 代码

//新增一个 androidSourcesJar 任务,将源码打包,最终打包一个 build/libs/XXX-sources.jar
tasks.register("androidSourcesJar", Jar::class.java) {
	archiveClassifier.set("sources")
	from(android.sourceSets["main"].java.srcDirs)
	from((android.sourceSets["main"].kotlin as DefaultAndroidSourceDirectorySet).srcDirs)
}

将 jar 和 aar 一起发布到 Maven 库,以及传递本项目依赖的远程库

publishing {
    publications {
        //以下 "aar" 可以自定义
        register("aar", MavenPublication::class.java) {
            this.groupId = projectGroupId
            this.artifactId = XXX
            artifact(tasks["androidSourcesJar"])//打包 jar
            artifact("$buildDir/outputs/aar/${XXX}_${version}.aar")//打包 aar

            //生成 POM 文件,将添加的远程库传递给主工程
            //大致思路时遍历添加该 Module 下通过 implementation 依赖的所有远程库

            pom {
              withXml {
               val root = asNode()
               val dependencies = (root["dependencies"] as groovy.util.NodeList).firstOrNull() as groovy.util.Node?
                ?: root.appendNode("dependencies")
               configurations.configureEach {
                this.dependencies.forEach {
                 if (this.name == "implementation" || this.name == "api") {
                  if (it.group?.isNotBlank() == true && (it.name.isNotBlank() || "unspecified" != it.name) && it.version?.isNotBlank() == true) {
                   val dependency = dependencies.appendNode("dependency")
                   dependency.appendNode("groupId", it.group)
                   dependency.appendNode("artifactId", it.name)
                   dependency.appendNode("version", it.version)
                   dependency.appendNode("scope", "implementation")
                  }
                 }
                }
               }
              }
            }
        }
    }
}

最终生成 /build/publications/XXX/pom-default.xml 文件,形式如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.xxxxx.xxx</groupId>
  <artifactId>ui</artifactId>
  <version>0.2.1-SNAPSHOT</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>com.github.goweii</groupId>
      <artifactId>Layer</artifactId>
      <version>1.0.5</version>
      <scope>implementation</scope>
    </dependency>
    <dependency>
      <groupId>androidx.core</groupId>
      <artifactId>core-ktx</artifactId>
      <version>1.10.1</version>
      <scope>implementation</scope>
    </dependency>
    <dependency>
      <groupId>androidx.appcompat</groupId>
      <artifactId>appcompat</artifactId>
      <version>1.6.1</version>
      <scope>implementation</scope>
    </dependency>
    <dependency>
      <groupId>com.google.android.material</groupId>
      <artifactId>material</artifactId>
      <version>1.9.0</version>
      <scope>implementation</scope>
    </dependency>
  </dependencies>
</project>

修改 Jrog 插件的 artifactoryPublish 任务

tasks.named<ArtifactoryTask>("artifactoryPublish") {
	artifactory {
		setContextUrl(mavenArtifactoryUrl)
		clientConfig.publisher.repoKey = xxx
		clientConfig.publisher.username = "xxx"//maven 库用户名
		clientConfig.publisher.password = "xxx"//maven 库密码
	}
	dependsOn(tasks["assemble"])
        //"aar" 同上
	publications(publishing.publications["aar"])
}

Gradle Kotlin DSL 读取 gradle.properties 中定义的值

比如在 gradle.properties 有这么两个值

localDependency = false
isSnapshot = true

那么,在 build.gradle.kts 文件中

val localDependency : String by project
val isSnapshot: String by project

通过自带的委托属性获取同名值,必须同名,且只能 String 类型,没有摸索到如何转为 Boolean 值,有知道的朋友可以告知。

注: 有同学提醒可以用 .toBoolean() 来转为布尔类型