How to generate javadoc for android library when it has dependencies which are also aar libraries?

I have an Android library project that depends on other Android library projects. I need to generate javadoc for the library, but it fails because gradle puts the path of the javadoc classpath in .aar, but javadoc expects .jar files.

simplified gradle file:

android { compileSdkVersion 23 buildToolsVersion "23.0.2" configurations { javadocDeps } defaultConfig { minSdkVersion 7 targetSdkVersion 23 versionCode 1 versionName "0.1.0" } } dependencies { compile 'com.android.support:support-v4:23.2.0' compile 'com.android.support:appcompat-v7:23.2.0' compile 'com.nineoldandroids:library:2.4.0' compile 'com.annimon:stream:1.0.7' javadocDeps 'com.android.support:support-annotations:23.2.0' javadocDeps 'com.nineoldandroids:library:2.4.0' javadocDeps 'com.android.support:support-v4:23.2.0' } task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' } task javadoc(type: Javadoc, dependsOn: explodeAars) { source = android.sourceSets.main.java.srcDirs classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) classpath += configurations.javadocDeps } task javadocJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from javadoc.destinationDir } artifacts { archives javadocJar archives sourcesJar } 

3 solutions are possible:

1) somehow add classes.jar from each aar library to the classpath, it depends on the assembly / intermidiates / exploded -aar / library / version / jars / classes.jar I don’t know how to include these paths in the javadoc task.

2) manually unzip class.jar from aar file and add them to the javadoc task class path

3) a very dirty hack - hard-coded paths to the library - but I think this is so WRONG.

How to reach 1 or 2 with gradle dsl?

+6
source share
5 answers

The solution from @rve is now broken on Android Studio 2.3 / Gradle 3.3, since exploded-aar no longer exists (without an alternative inside the build directory).

If the aar you depend on is not a module in your project, you need to first extract class.jar before referencing it in the classpath (basically re-create intermediates/exploded-aar manually).

If the aar you rely on is another module in your project, you can also make your javadoc task dependent on the compilation task of this module and refer to intermediates/classes/release this module (if you make javadoc dependent on assembleRelease, for example) . An example of this workaround: https://github.com/Microsoft/mobile-center-sdk-android/pull/345/files

I really want someone to come up with a better solution.

+4
source

I managed to automate the Guillaume Perrot solution by extracting the classes.jar contained in each AAR file and adding it to the javadoc task class path.

It seems to work for AAR dependencies and AAR modules on Android Studio 2.3 and Gradle 3.3

 import java.nio.file.Files import java.nio.file.Paths import java.io.FileOutputStream import java.util.zip.ZipFile task javadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs classpath += configurations.compile classpath += configurations.provided afterEvaluate { // Wait after evaluation to add the android classpath // to avoid "buildToolsVersion is not specified" error classpath += files(android.getBootClasspath()) // Process AAR dependencies def aarDependencies = classpath.filter { it.name.endsWith('.aar') } classpath -= aarDependencies aarDependencies.each { aar -> // Extract classes.jar from the AAR dependency, and add it to the javadoc classpath def outputPath = "$buildDir/tmp/aarJar/${aar.name.replace('.aar', '.jar')}" classpath += files(outputPath) // Use a task so the actual extraction only happens before the javadoc task is run dependsOn task(name: "extract ${aar.name}").doLast { extractEntry(aar, 'classes.jar', outputPath) } } } } // Utility method to extract only one entry in a zip file private def extractEntry(archive, entryPath, outputPath) { if (!archive.exists()) { throw new GradleException("archive $archive not found") } def zip = new ZipFile(archive) zip.entries().each { if (it.name == entryPath) { def path = Paths.get(outputPath) if (!Files.exists(path)) { Files.createDirectories(path.getParent()) Files.copy(zip.getInputStream(it), path) } } } zip.close() } 
+6
source

This only works for Android Studio older than 2.3 and / or Gradle older than 3.3

To add a JAR from an AAR, you can add the following doFirst task to the javadoc task:

 task javadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs } .doFirst { classpath += fileTree(dir: "$buildDir/intermediates/exploded-aar/", include:"**/classes.jar") } 

It will add all .jar files from all AARs to the javadoc class path. (option 1 of your proposed solutions)

+4
source

I am launching a new Android Studio 3.0-beta7 and trying to use @nicopico's answer, but it did not work with a number of different errors, so here is an adaptation that does not rely on non-existent java.nio utilities.

 task javadoc(type: Javadoc) { failOnError false source = android.sourceSets.main.java.srcDirs // Also add the generated R class to avoid errors... // TODO: debug is hard-coded source += "$buildDir/generated/source/r/debug/" // ... but exclude the R classes from the docs excludes += "**/R.java" // TODO: "compile" is deprecated in Gradle 4.1, // but "implementation" and "api" are not resolvable :( classpath += configurations.compile afterEvaluate { // Wait after evaluation to add the android classpath // to avoid "buildToolsVersion is not specified" error classpath += files(android.getBootClasspath()) // Process AAR dependencies def aarDependencies = classpath.filter { it.name.endsWith('.aar') } classpath -= aarDependencies aarDependencies.each { aar -> System.out.println("Adding classpath for aar: " + aar.name) // Extract classes.jar from the AAR dependency, and add it to the javadoc classpath def outputPath = "$buildDir/tmp/exploded-aar/${aar.name.replace('.aar', '.jar')}" classpath += files(outputPath) // Use a task so the actual extraction only happens before the javadoc task is run dependsOn task(name: "extract ${aar.name}").doLast { extractEntry(aar, 'classes.jar', outputPath) } } } } // Utility method to extract only one entry in a zip file private def extractEntry(archive, entryPath, outputPath) { if (!archive.exists()) { throw new GradleException("archive $archive not found") } def zip = new java.util.zip.ZipFile(archive) zip.entries().each { if (it.name == entryPath) { def path = new File(outputPath) if (!path.exists()) { path.getParentFile().mkdirs() // Surely there a simpler is->os utility except // the one in java.nio.Files? Ah well... def buf = new byte[1024] def is = zip.getInputStream(it) def os = new FileOutputStream(path) def len while ((len = is.read(buf)) != -1) { os.write(buf, 0, len) } os.close() } } } zip.close() } 

My concern is that we need all this code to create freaking javadoc for the library, but at least I got this working. However, I need to find a workaround for the .api configuration and configuration.implementation are not solvable.

+1
source

This is how I solved this problem using zipTree . Configuration: Gradle 4.10, Gradle Plugin: 3.3.2, Android Studio: 3.4.

 task javadoc(type: Javadoc) { doFirst { configurations.implementation .filter { it.name.endsWith('.aar') } .each { aar -> copy { from zipTree(aar) include "**/classes.jar" into "$buildDir/tmp/aarsToJars/${aar.name.replace('.aar', '')}/" } } } configurations.implementation.setCanBeResolved(true) source = android.sourceSets.main.java.srcDirs classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) classpath += configurations.implementation classpath += fileTree(dir: "$buildDir/tmp/aarsToJars/") destinationDir = file("${project.buildDir}/outputs/javadoc/") failOnError false exclude '**/BuildConfig.java' exclude '**/R.java' } 
0
source

Source: https://habr.com/ru/post/1244607/


All Articles