2016-03-07 6 views
5

Ich habe Android-Bibliothek-Projekt, das auf andere Android-Bibliothek Projekte abhängt. Ich muss Javadoc für die Bibliothek generieren, aber es schlägt fehl, weil Gradle den Javadoc-Klassenpfadpfad auf .aar-Speicherorte setzt, aber Javadoc JAR-Dateien erwartet.Wie generiere ich Javadoc für Android-Bibliothek, wenn es Abhängigkeiten hat, die auch AAR-Bibliotheken sind?

vereinfachte gradle Datei:

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 Lösungen möglich:

1) irgendwie mit dem Classpath Weg classes.jar von jeder aar Bibliothek hinzufügen bauen hängt/intermidiates/Explosions-aar/Bibliothek /version/jars/classes.jar Ich weiß nicht, wie diese Pfade in die Javadoc-Aufgabe eingefügt werden sollen.

2) manuell classes.jar aus aar-Datei entpacken und sie Aufgabe Classpath von javadoc

3) sehr schmutzig Hack hinzufügen - fest einprogrammierten Pfade Bibliothek - aber ich denke, das ist so falsch.

Wie erreicht man 1 oder 2 mit Gradle DSL?

+0

Verwenden Sie Android Studio? Es gibt in Tools> Generate JavaDoc ein praktisches Werkzeug um auszuwählen, was der Javadoc benötigt. – xiaomi

+0

Ich benutze Android Studio, aber diese Aufgabe muss automatisch auf remote jenkins Instanz durchgeführt werden. Diese Aufgabe zum Hochladen der Bibliothek in jcenter/mavenCentral – curioushikhov

Antwort

4

Die Lösung von @rve ist jetzt in Android Studio 2.3/Gradle 3.3 nicht mehr vorhanden, da exploded-aar nicht mehr existiert (ohne Alternative im Build-Verzeichnis).

Wenn das aar, auf das Sie angewiesen sind, kein Modul in Ihrem Projekt ist, müssen Sie die classes.jar zuerst extrahieren, bevor Sie sie im Klassenpfad referenzieren (erstellen Sie im Grunde intermediates/exploded-aar manuell neu). Wenn das aar, auf das Sie angewiesen sind, nur ein anderes Modul in Ihrem Projekt ist, können Sie Ihre javadoc-Aufgabe auch von der Kompilieraufgabe des Moduls abhängig machen und auf die intermediates/classes/release dieses Moduls verweisen (wenn Sie javadoc von assemblyRelease abhängig machen) . Ein Beispiel für diese Problemumgehung: https://github.com/Microsoft/mobile-center-sdk-android/pull/345/files

Ich wünschte wirklich, dass jemand mit einer besseren Lösung obwohl kommt.

5

Dies funktioniert nur für Android Studio älter als 2.3 und/oder Gradle älter als 3,3

die JAR-Dateien hinzufügen aus der AARs Sie folgende doFirst zum javadoc Aufgabe hinzufügen:

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

Es fügt alle .jar Dateien aus allen AARs dem Javadoc-Klassenpfad hinzu. (Option 1 von Ihren vorgeschlagenen Lösungen)

+4

Dies ist jetzt mit Android Studio 2.3/Gradle 3.3 gebrochen. Das exploded-aar-Verzeichnis existiert nicht mehr. –

+0

eine Randnotiz: Dies funktioniert nicht für Bibliotheksprojekte in mit dem android Gradle Plugin 2.3.3 – NemoOudeis

6

ich es geschafft, die Lösung von Guillaume Perrot durch Extraktion der classes.jar in jeder AAR-Datei enthalten sind, zu automatisieren und zu dem Classpath der javadoc Aufgabe hinzufügen.

Es ist für AAR Abhängigkeiten und AAR-Module auf Android Studio 2.3 und 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() 
} 
+0

Great Job! Das scheint mir gut zu gehen! Verwenden von Gradle 3.3. –

+0

Das hat bei mir nicht funktioniert, aber ich benutze das gradle plugin 3.0 im kanarischen Kanal (Android Studio 3.0-beta 7). Ich musste die "bereitgestellte" Konfiguration entfernen, um es zu kompilieren, aber das Ergebnis ist wie zuvor - javadoc Erzeugung schlägt fehl, weil externe Abhängigkeiten nicht aufgelöst werden. – JHH

+0

Mit com.android.tools.build:gradle:3.0.0-beta7 und daher Gradle-4.1, bekomme ich mehrere verschiedene Probleme. Zuallererst sind einige der java.nio-Klassen nicht verfügbar, also habe ich Ihren Code ohne 'Paths' und' Files' umgeschrieben. Das nächste Problem war, dass die neuen Konfigurationen "API" und "Implementierung" nicht auflösbar sind. Daher musste ich auf Compile-Abhängigkeiten zurückgreifen. Danach schlägt es immer noch fehl, weil es seine eigene R-Klasse nicht finden kann. Nach dem manuellen Hinzufügen von/build/generated/source/r/debug habe ich ein funktionierendes Javadoc erstellt. Aber ich brauche wirklich die neuen Direktiven zu funktionieren. – JHH

1

Ich bin mit dem neuen Android Studio 3.0-beta7 scheint zu funktionieren, und versuchte @ nicopico Antwort zu verwenden, aber es ist fehlgeschlagen mit einer Reihe von verschiedenen Fehlern, so ist hier eine Anpassung davon, die nicht auf die nicht vorhandenen java.nio Dienstprogramme angewiesen ist.

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() 
} 

Es stört mich, dass wir alle diesen Code brauchen eine freaking javadoc für eine Bibliothek zu produzieren, aber zumindest habe ich diese Arbeit. Allerdings muss ich eine Problemumgehung für configuration.api und configuration.implementation nicht auflösbar finden.

+0

Separate Frage auch gefragt: https://stackoverflow.com/questions/46810769/how-to-get-dependencies-from-a-gradle-plugin-using-api-or-implementation-dir – JHH

Verwandte Themen