Android library publication in 2020

Using Gradle 6, Kotlin DSL and Dokka.

Many guides and how-to’s about publishing Android libraries use outdated information. While the (deprecated) Gradle maven plugin, bintray or artifactory plugins continue to work just fine, things look a little different when using Gradle Kotlin DSL. Also, when creating Android libraries written in Kotlin, code documentation should use Dokka, not Javadoc. The examples used in this post are based of android-customtabs, a convenience library for Chrome CustomTabs.

Gradle plugins

We’ll be using the modern maven-publish plugin for uploading and Jetbrains’ Dokka plugin to build the code documentation:

plugins {
    // ...
    id("org.jetbrains.dokka") version "0.10.1"
    `maven-publish`
}

As usual, any publication that is meant to be published to a Maven repository, needs a group and version under which to publish the artifacts. In the case of Android libraries, you can take the version directly from the Android Gradle plugin’s default configuration, in our case:

group = "saschpe.android"
version = android.defaultConfig.versionName.toString()

Documentation Jar

Code documentation for Kotlin can be generated with Dokka:

tasks {
    val dokkaJavadoc by creating(org.jetbrains.dokka.gradle.DokkaTask::class) {
        outputFormat = "javadoc"
        outputDirectory = "$buildDir/javadoc"
        configuration {
            sourceLink {
                path = "src/main/java"
                url = "https://github.com/saschpe/android-customtabs/tree/master/customtabs/src/main/java"
                lineSuffix = "#L"
            }
        }
    }

    register("androidJavadocJar", Jar::class) {
        archiveClassifier.set("javadoc")
        from("$buildDir/javadoc")
        dependsOn(dokkaJavadoc)
    }
    // ...

Sources Jar

In addition, the source code of your library (it’s Open Source, isn’t it?) should get published alongside to simplify debugging and inspection. The necessary task is straightforward:

    // ...
    register("androidSourcesJar", Jar::class) {
        archiveClassifier.set("sources")
        from(android.sourceSets.getByName("main").java.srcDirs)
    }
}

What to publish?

Uploading an Android Archive release build is enough to let others use it. However, development with you library is simplified if Gradle can resolve the code documentation and sources automatically. Thus, add them to your publication:

publishing {
    publications {
        register<MavenPublication>("mavenAndroid") {
            artifactId = "customtabs"

            afterEvaluate { artifact(tasks.getByName("bundleReleaseAar")) }
            artifact(tasks.getByName("androidJavadocJar"))
            artifact(tasks.getByName("androidSourcesJar"))

Metadata

You have to provide a name and description of your library as well as it’s licensing terms. Don’t forget to mention your Github project, the issue tracker, etc.

            pom {
                name.set("Android CustomTabs")
                description.set("Chrome CustomTabs for Android demystified. Simplifies development and provides higher level classes including fallback in case Chrome isn't available on device.")
                url.set("https://github.com/saschpe/android-customtabs")

                licenses {
                    license {
                        name.set("The Apache License, Version 2.0")
                        url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
                    }
                }
                developers {
                    developer {
                        id.set("saschpe")
                        name.set("Sascha Peilicke")
                        email.set("sascha@peilicke.de")
                    }
                }
                scm {
                    connection.set("scm:git:git://github.com/saschpe/android-customtabs.git")
                    developerConnection.set("scm:git:ssh://github.com/saschpe/android-customtabs.git")
                    url.set("https://github.com/saschpe/android-customtabs")
                }

Declaring dependencies

Unfortunately, Gradle’s maven-publish plugin isn’t able to derive dependencies of your library from simply looking at your Gradle project’s dependencies. For now, you have to provide them explicitly:

                withXml {
                    fun groovy.util.Node.addDependency(dependency: Dependency, scope: String) {
                        appendNode("dependency").apply {
                            appendNode("groupId", dependency.group)
                            appendNode("artifactId", dependency.name)
                            appendNode("version", dependency.version)
                            appendNode("scope", scope)
                        }
                    }

                    asNode().appendNode("dependencies").let { dependencies ->
                        // List all "api" dependencies as "compile" dependencies
                        configurations.api.get().allDependencies.forEach {
                            dependencies.addDependency(it, "compile")
                        }
                        // List all "implementation" dependencies as "runtime" dependencies
                        configurations.implementation.get().allDependencies.forEach {
                            dependencies.addDependency(it, "runtime")
                        }
                    }
                }
            }
        }
    }

Where to upload?

Open Source Java or Kotlin libraries are usually published to Maven Central / Sonatype or jCenter / Bintray. The latter is easier to set up and allows to sync to the former:

    // ...
    repositories {
        maven {
            name = "bintray"
            credentials {
                username = Secrets.Bintray.user
                password = Secrets.Bintray.apiKey
            }
            url = uri("https://api.bintray.com/maven/saschpe/maven/android-customtabs/;publish=1")
        }
    }
}

That’s it. You can find the entire Grade sources on Github. The library is published on Bintray.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.