当它具有也是 aar 库的依赖项时,如何为 android 库生成 javadoc?
Posted
技术标签:
【中文标题】当它具有也是 aar 库的依赖项时,如何为 android 库生成 javadoc?【英文标题】:How to generate javadoc for android library when it has dependencies which are also aar libraries? 【发布时间】:2016-06-21 14:28:48 【问题描述】:我有依赖于其他 android 库项目的 android 库项目。我需要为库生成 javadoc,但它失败了,因为 gradle 将 javadoc 类路径放入 .aar 位置,但 javadoc 需要 .jar 文件。
简化的 gradle 文件:
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 种可能的解决方案:
1) 以某种方式从它依赖的每个 aar 库添加到类路径路径 classes.jar build/intermidiates/exploded-aar/library/version/jars/classes.jar 我不知道如何在 javadoc 任务中包含这些路径。
2) 手动从aar文件中解压classes.jar并将它们添加到javadoc任务的classpath中
3) 非常肮脏的 hack - 库的硬编码路径 - 但我认为这是非常错误的。
如何用gradle dsl实现1或2?
【问题讨论】:
你用的是安卓工作室吗?在 Tools > Generate JavaDoc 中有一个方便的工具来选择 javadoc 需要采取的内容。 我使用 android studio,但是这个任务必须在远程 jenkins 实例上自动完成。此任务用于将库上传到 jcenter/mavenCentral 【参考方案1】:我通过提取每个 AAR 文件中包含的 classes.jar
并将其添加到 javadoc 任务的类路径中,成功地自动化了 Guillaume Perrot 的解决方案。
它似乎适用于 Android Studio 2.3 和 Gradle 3.3 上的 AAR 依赖项和 AAR 模块
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()
【讨论】:
干得好!这似乎对我很有效!使用 gradle 3.3。 这对我不起作用,但我在金丝雀频道(Android Studio 3.0-beta 7)中使用了 gradle 插件 3.0。我必须删除“提供的”配置才能编译它,但结果和以前一样 - javadoc 生成失败,因为没有解决外部依赖关系。 使用 com.android.tools.build:gradle:3.0.0-beta7 和 gradle-4.1,我遇到了几个不同的问题。首先,一些java.nio类不可用,所以我重写了你的代码,没有Paths
和Files
。下一个问题是新配置api
和implementation
无法解析,所以我不得不求助于使用compile
依赖项。这样做之后它仍然失败,因为它找不到自己的 R 类。手动添加 /build/generated/source/r/debug 后,我得到了一个工作的 javadoc。但我真的需要新指令才能工作..
我的@nicopico 代码的调整版本作为替代答案发布在下面。非常感谢您@nicopico 的努力!!【参考方案2】:
@rve 的解决方案现在在 Android Studio 2.3 / Gradle 3.3 上被破坏,因为 exploded-aar
不再存在(在构建目录中没有替代方案)。
如果你依赖的 aar 不是你项目中的一个模块,你需要先提取 classes.jar,然后在类路径中引用它(基本上是手动重新创建 intermediates/exploded-aar
)。
如果您所依赖的 aar 只是项目中的另一个模块,您还可以使您的 javadoc 任务依赖于该模块的编译任务并引用该模块的 intermediates/classes/release
(例如,如果您使 javadoc 依赖于 assembleRelease )。该解决方法的一个示例:https://github.com/Microsoft/mobile-center-sdk-android/pull/345/files
我真的希望有人提出更好的解决方案。
【讨论】:
【参考方案3】:这仅适用于早于 2.3 的 Android Studio 和/或早于 3.3 的 Gradle
要从 AAR 添加 JAR,您可以将以下 doFirst
添加到 javadoc 任务:
task javadoc(type: Javadoc)
source = android.sourceSets.main.java.srcDirs
.doFirst
classpath += fileTree(dir: "$buildDir/intermediates/exploded-aar/", include:"**/classes.jar")
它会将所有 AAR 中的所有 .jar
文件添加到 javadoc 类路径中。 (您提出的解决方案中的选项 1)
【讨论】:
这在 Android Studio 2.3 / Gradle 3.3 中被打破了。已分解的 aar 目录不再存在。 附注:这不适用于带有 android gradle 插件 2.3.3 的库项目【参考方案4】:我正在运行新的 Android Studio 3.0-beta7,并尝试使用 @nicopico 的答案,但由于许多不同的错误而失败,所以这里有一个不依赖于不存在的 @987654322 的改编版@ 实用程序。
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's 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()
困扰我的是,我们需要所有这些代码来为一个库生成一个怪异的 javadoc,但至少我得到了这个工作。但是,我确实需要为 configuration.api 和 configuration.implementation 无法解析找到解决方法。
【讨论】:
还提出了单独的问题:***.com/questions/46810769/…【参考方案5】:这就是我使用zipTree
解决此问题的方法。配置:Gradle 4.10,Gradle 插件: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'
【讨论】:
【参考方案6】:如果您正在使用 Kotlin 开发 Android 应用/库,则此处列出的所有解决方案都已过时。要生成 javadocs 以及其他几种格式的文档,请使用 KDoc 和 Dokka:
https://kotlinlang.org/docs/kotlin-doc.html
https://kotlin.github.io/dokka/1.5.0/
https://github.com/Kotlin/dokka
【讨论】:
以上是关于当它具有也是 aar 库的依赖项时,如何为 android 库生成 javadoc?的主要内容,如果未能解决你的问题,请参考以下文章