Search code examples
androidandroid-gradle-pluginandroid-librarymaven-publish

How can I add docstrings to android maven-publish .aar files in build.gradle.kts?


I have a project with the standard java library and this creates several .jar files, one being a docset and another the source set. Now I have successfully created an android-library using the maven-publish plugin, but when I add the .aar files to another project, they don't contain neither source nor comments as the .jar version did, so I don't get help inside the IDE or look into the implementation of methods.

What do I need to add to my build.gradle.kts to include docstrings and sources in the debug version of the .aar I'm publishing locally as a file? The linked gradle documentation from that Android developer page does not mention anything about docstrings or sources at all.

import org.jetbrains.kotlin.config.KotlinCompilerVersion

plugins {
    id("com.android.library")
    kotlin("android")
    `maven-publish`
}

group = "com.wavelt.libs"
version = "1.0.0"


android {
    compileSdkVersion(30)
    buildToolsVersion = "30.0.2"
    defaultConfig {
        minSdkVersion(16)
        targetSdkVersion(30)
        versionCode = 1
        versionName = "1.0.0"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles("consumer-rules.pro")
    }
    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
        freeCompilerArgs = listOf("-Xinline-classes")
    }
}

dependencies {
    implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION))
    implementation("androidx.core:core-ktx:1.3.2")
    implementation("androidx.appcompat:appcompat:1.2.0")
    implementation("com.google.android.material:material:1.3.0")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.2")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0")
    androidTestImplementation("com.android.support.test:runner:1.0.2")
    androidTestImplementation("com.android.support.test:rules:1.0.2")
}

// https://developer.android.com/studio/build/maven-publish-plugin
afterEvaluate {
    publishing {
        repositories {
            maven {
                // https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:repositories
                url = uri("$buildDir/repository")
            }
        }
        publications {
            create<MavenPublication>("debug") {
                // Applies the component for the release build variant.
                from(components["debug"])
                artifactId = "wavelt-android-debug"
                artifact("androidJavadocsJar") // Doesn't seem to work
            }
            create<MavenPublication>("release") {
                // Applies the component for the release build variant.
                from(components["release"])
                artifactId = "wavelt-android"
            }
        }
    }
}

Solution

  • While I've read about other devs being able to cram the javadocs into the .aar file, this is not explicitly necessary at all to gain documentation and source code inspection from inside IDEs like Android Studio. In fact, looking at the way a typical java library works, it creates files like:

    • foo-ver.jar
    • foo-ver-sources.jar
    • foo-ver-javadoc.jar

    The only difference with an Android library would be having these files:

    • foo-ver.aar
    • foo-ver-sources.jar
    • foo-ver-javadoc.jar

    Which means that the sources and javadoc jars can still be copied along the .aar and the IDE will load them. Having said that, the publish example code only creates the .aar file, looking at other questions like this one I was able to modify the script to create the .aar plus the two other .jar packages:

    import org.jetbrains.kotlin.config.KotlinCompilerVersion
    
    plugins {
        id("com.android.library")
        kotlin("android")
        `maven-publish`
        id("org.jetbrains.dokka") version "0.9.17"
    }
    
    group = "com.wavelt.libs"
    version = "1.0.0"
    
    
    android {
        compileSdkVersion(30)
        buildToolsVersion = "30.0.2"
        defaultConfig {
            minSdkVersion(16)
            targetSdkVersion(30)
            versionCode = 1
            versionName = "1.0.0"
            testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
            consumerProguardFiles("consumer-rules.pro")
        }
        buildTypes {
            getByName("release") {
                isMinifyEnabled = false
                proguardFiles(
                    getDefaultProguardFile("proguard-android-optimize.txt"),
                    "proguard-rules.pro"
                )
            }
        }
        compileOptions {
            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8
        }
        kotlinOptions {
            jvmTarget = "1.8"
            freeCompilerArgs = listOf("-Xinline-classes")
        }
    }
    
    dependencies {
        //implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
        implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION))
        implementation("androidx.core:core-ktx:1.3.2")
        implementation("androidx.appcompat:appcompat:1.2.0")
        implementation("com.google.android.material:material:1.3.0")
        testImplementation("junit:junit:4.13.2")
        androidTestImplementation("androidx.test.ext:junit:1.1.2")
        androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0")
        androidTestImplementation("com.android.support.test:runner:1.0.2")
        androidTestImplementation("com.android.support.test:rules:1.0.2")
    }
    
    tasks.dokka {
        outputFormat = "html"
        outputDirectory = "$buildDir/javadoc"
        moduleName = rootProject.name
    }
    
    val dokkaJar by tasks.creating(Jar::class) {
        group = JavaBasePlugin.DOCUMENTATION_GROUP
        description = "Assembles Kotlin docs with Dokka"
        archiveClassifier.set("javadoc")
        from(tasks.dokka)
        dependsOn(tasks.dokka)
    }
    
    val sourcesJar by tasks.creating(Jar::class) {
        group = JavaBasePlugin.DOCUMENTATION_GROUP
        description = "Assembles sources JAR"
        archiveClassifier.set("sources")
        from(android.sourceSets.getByName("main").java.srcDirs)
    }
    
    artifacts {
        archives(sourcesJar)
        archives(dokkaJar)
    }
    
    // https://developer.android.com/studio/build/maven-publish-plugin
    afterEvaluate {
        publishing {
            repositories {
                maven {
                    // https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:repositories
                    url = uri("$buildDir/repository")
                }
            }
            publications {
                create<MavenPublication>("debug") {
                    // Applies the component for the release build variant.
                    from(components["debug"])
                    artifactId = "wavelt-android-debug"
                    artifact(sourcesJar)
                    artifact(dokkaJar)
                }
                create<MavenPublication>("release") {
                    // Applies the component for the release build variant.
                    from(components["release"])
                    artifactId = "wavelt-android"
                }
            }
        }
    }
    

    With these modifications the ./gradlew publish task will generate all files, and despite one of them having .aar they work the same as .jar when copied together into another project.