Stuart Kent
(Android Developer)

Adventures With Javadocs (Part 1)

Part of publishing high-quality libraries is providing high-quality documentation, which in Android-land means: high-quality Javadocs. There are tons of good resources around that explain proper Javadoc comment format and content, so in this series we’ll explore the actual generation of documentation using Gradle/Android Studio.

Javadoc Task Type Basics

The Gradle Java plugin provides a template Javadoc task with the following description:

Generates HTML API documentation for Java classes.

If you create your own Javadoc tasks remember to specify the ‘source’ property! Without source the Javadoc task will not create any documentation.

For an Android library project, the simplest configuration of this task would therefore be:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
        versionName "1.0.0"
    }
}

task docs(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
}

[This assumes a project with no other dependencies, no flavor/type/variant-specific source files, etc.]

Let’s add a super-simple pair of test classes to the project, each in their own package:

package com.github.stkent.javadoctests.package1;

/**
 * This class depends on an automatically-imported type only!
 */
public class TestClassOne {

    private String string;

    public TestClassOne(String string) { this.string = string; }

    public String getString() { return string; }

}
package com.github.stkent.javadoctests.package2;

import com.github.stkent.javadoctests.package1.TestClassOne;

/**
 * This class depends on a user-created and -imported type only!
 */
public class TestClassTwo {

    private TestClassOne testClassOne;

    public TestClassTwo(TestClassOne testClassOne) { this.testClassOne = testClassOne; }

    public TestClassOne getTestClassOne() { return testClassOne; }

}

and generate Javadocs by executing our new docs task:

./gradlew library:clean library:docs

which produces the following output files:

Note in particular that the directory structure of the generated website matches the package structure of the original source files. For example, the class TestClassOne is part of the com.github.stkent.javadoctests.package1 package, and its corresponding documentation page is inside the com/github/stkent/javadoctests/package1 subdirectory of the generated website.

Generated Documentation

Before proceeding, I’d like to review a pair of sample pages from this output. This will provide some important context for the next post in this series.

Here’s the summary generated for TestClassOne:

and the corresponding summary generated for TestClassTwo:

The TestClassTwo constructor signature includes a hyperlink to the generated documentation page for its lone parameter type (TestClassOne). Based on the correspondence between directory structure and package structure we identified earlier, I would postulate that the javadoc tool generates this link by parsing the following import statement in TestClassTwo:

import com.github.stkent.javadoctests.package1.TestClassOne;

On the other hand, because the Java String type is not part of the source we provided to the docs task, the javadoc tool has no way of determining an equivalent hyperlink target to use for the TestClassOne constructor parameter type.

Under The Hood

Gradle’s Javadoc task type acts as a wrapper around the command-line javadoc tool included with every JDK. To locate yours, run which javadoc from the command line (the path to this file should match your JAVA_HOME environment variable, if set):

$ which javadoc
/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/bin/javadoc

The temporary javadoc.options file generated by our Gradle task contains options and arguments that are forwarded to this command-line tool. For our example, the javadocs.options file contains these lines:

-d '/Users/stuart/dev/personal/libraries/JavadocTests/library/build/docs/javadoc'
-doctitle 'library API'
-quiet 
-windowtitle 'library API'
'/Users/stuart/dev/personal/libraries/JavadocTests/library/src/main/java/com/github/stkent/javadoctests/package1/TestClassOne.java'
'/Users/stuart/dev/personal/libraries/JavadocTests/library/src/main/java/com/github/stkent/javadoctests/package2/TestClassTwo.java'

This is pretty minimal configuration - we are setting the output directory, titles to use for the generated website, and providing the collection of source files for which we would like documentation to be generated. To confirm the claim that Gradle’s Javadoc task calls javadoc with these options and arguments, we can run:

./gradlew library:clean

followed by:

javadoc -d '/Users/stuart/dev/personal/libraries/JavadocTests/library/build/docs/javadoc' -doctitle 'library API' -quiet -windowtitle 'library API' '/Users/stuart/dev/personal/libraries/JavadocTests/library/src/main/java/com/github/stkent/javadoctests/package1/TestClassOne.java' '/Users/stuart/dev/personal/libraries/JavadocTests/library/src/main/java/com/github/stkent/javadoctests/package2/TestClassTwo.java'

which produces the output files shown below (viewed within Android Studio):

This is identical to the output of the Gradle task itself, minus the temporary javadoc.options file! Which is neat, because it means we can leverage all the existing javadoc tool documentation to help us overcome some of the challenges we’ll be facing in the next post, in which we add classes from the Android framework and third-party dependencies to our sample project.

The code for this post is available here.