Abhängigkeiten zwischen Tools und Bibliotheken

Buildabhängigkeiten sind externe Komponenten, die für den erfolgreichen Build Ihres Projekts erforderlich sind. Ein Build kann von Bibliotheken, Plug-ins, Unterprojekten, dem Android SDK, Tools wie Kotlin- und Java-Compilern, Entwicklungsumgebungen wie Android Studio und Gradle selbst abhängen.

Für jede Abhängigkeit können wiederum andere Abhängigkeiten erforderlich sein. Diese werden als transitive Abhängigkeiten bezeichnet. Sie können die von Ihrer Anwendung verwendeten Gesamtabhängigkeiten schnell erhöhen. Wenn Sie eine Abhängigkeit aktualisieren möchten, unabhängig davon, ob es sich um eine Bibliothek, ein Tool oder das Android SDK handelt, kann dieses Upgrade kaskadiert werden, wodurch viele andere Abhängigkeiten aktualisiert werden.

Oft ist das kein Problem, da viele Bibliotheken dem semantischen Versionierungsschema folgen. Diese Bibliotheken beschränken die Arten von Änderungen, die sie vornehmen, um für die Kompatibilität mit niedrigeren Versionen zu sorgen.

Die semantische Versionsverwaltung folgt dem Format major.minor.patch. Beispiel: In der Versionsnummer 4.8.3 ist 4 die major-Version, 8 die minor-Version und 3 die Nummer patch. Wenn sich der Teil major ändert, kann es zu gravierenden Änderungen an der API oder dem Verhalten der Bibliothek kommen. Dies kann sich auf das Build- oder Anwendungsverhalten auswirken.

Wenn sich die Teile minor (neue Funktionen) oder patch (Fehlerkorrekturen) ändern, geben die Bibliotheksentwickler an, dass die Bibliothek weiterhin kompatibel ist und sich nicht auf Ihre Anwendung auswirken sollte.

Es ist wichtig, auf solche Änderungen zu achten. Dabei können mehrere Tools zur Abhängigkeitsaktualisierung helfen.

Beziehungen in Ihrem Build

Android-Builds enthalten Beziehungen zwischen:

  • Quellcode: Code und Ressourcen, über die Sie die Kontrolle haben
  • Bibliotheksabhängigkeiten: Externe Bibliotheken oder Module, die Ihr Projekt und Ihre Unterprojekte beim Erstellen
  • Tools: Compiler, Plug-ins und SDKs, die Ihre Quelle in eine Anwendung oder Bibliothek umwandeln
Abhängigkeiten und ihre Beziehungen aufbauen
Abbildung 1: Beziehungen aufbauen

Quellcode

Ihr Quellcode ist Kotlin- oder Java-Code, den Sie in Ihre Anwendung oder Bibliothek schreiben. Weitere Informationen zur Verwendung von C++ finden Sie unter Android NDK.

Der Quellcode ist von Bibliotheken (einschließlich Kotlin- und Java-Laufzeitbibliotheken) und dem Android SDK abhängig und erfordert den entsprechenden Kotlin- oder Java-Compiler.

Einige Quellcodes enthalten Anmerkungen, die eine zusätzliche Verarbeitung erfordern. Wenn Sie beispielsweise Jetpack Compose-Code schreiben, fügen Sie Anmerkungen wie @Composable hinzu, die vom Compose Kotlin-Compiler-Plug-in verarbeitet werden müssen. Andere Anmerkungen können von einem Kotlin Symbol Processor (KSP) oder separaten Tools zur Anmerkungsverarbeitung verarbeitet werden.

Bibliotheksabhängigkeiten

Bibliotheken enthalten Bytecode, der als Teil Ihrer Anwendung abgerufen wurde. Dies kann eine Java-JAR-Datei, eine Android-Bibliothek (AAR) oder ein Unterprojekt in Ihrem Build sein. Viele Bibliotheken folgen der semantischen Versionsverwaltung. So können Sie besser nachvollziehen, ob sie nach einem Upgrade weiterhin kompatibel sind oder nicht.

Bibliotheken können zur Wiederverwendung von anderen Bibliotheken abhängig sein, was als transitive Abhängigkeit bezeichnet wird. Dadurch werden die Abhängigkeiten reduziert, die Sie explizit verwalten müssen. Sie geben die Abhängigkeiten an, die Sie direkt verwenden, und Gradle ruft sie zusammen mit diesen transitiven Abhängigkeiten ab. Beachten Sie, dass durch das Upgrade Ihrer direkten Abhängigkeiten auch diese transitiven Abhängigkeiten aktualisiert werden können.

Manchmal sind für eine Bibliothek zur Laufzeit (minSdk) oder Kompilierungszeit (compileSdk) Mindestversionen des Android SDK erforderlich. Dies ist erforderlich, wenn eine Bibliothek Funktionen verwendet, die im Android SDK oder in den bereitgestellten JDK APIs enthalten sind. Die effektive minSdk Ihrer Anwendung ist die höchste minSdk, die von Ihrer Anwendung und allen direkten und transitiven Bibliotheksabhängigkeiten angefordert wird.

Für die Verwendung einiger Bibliotheken ist möglicherweise ein bestimmtes Gradle-Plug-in erforderlich. Diese Hilfs-Plug-ins installieren häufig Kotlin-Symbolprozessoren oder andere Anmerkungs-Prozessoren, die Code generieren oder die Kompilierung Ihrer Quelle ändern, um die Verwendung von Bibliotheksfunktionen zu unterstützen. Jetpack Room enthält beispielsweise Anmerkungen und einen KSP, der sie in generierten Code umwandelt, um Daten in einer Datenbank abzurufen und zu ändern. Für Jetpack Compose muss das Compose-Compiler-Plug-in annotierte Funktionen ändern, um zu verwalten, wie und wann diese Funktion noch einmal ausgeführt wird.

Tools

Gradle

Gradle ist das Build-Tool, das Ihre Build-Dateien liest und Ihre Anwendung oder Bibliothek generiert. Außerdem stellt es eine API für Plug-ins bereit, um die Funktionen zu erweitern. Gradle führt mehrere Prozesse auf einer oder mehreren virtuellen Java-Maschinen aus und die Java-Plug-ins rufen die Java-Tools im JDK auf.

Gradle-Plug-ins

Gradle-Plug-ins erweitern Gradle durch das Definieren neuer Aufgaben und Konfigurationen. Wenn Sie ein Plug-in auf Ihren Build anwenden, werden bestimmte Build-Funktionen aktiviert, die in Ihren Build-Scripts als Daten konfiguriert sind. Das wichtigste Gradle-Plug-in für Android-Builds ist das Android Gradle Plugin (AGP).

Compiler

Der Kotlin- oder Java-Compiler wandelt Ihren Quellcode in ausführbaren Bytecode um. Der Kotlin-Compiler stellt eine Plug-in-API bereit, mit der externe Analysen und die Codegenerierung direkt im Compiler ausgeführt werden können, um auf die geparste Codestruktur zuzugreifen.

Compiler-Plug-ins

Compiler-Plug-ins führen Analysen und Codegenerierung innerhalb des Kotlin-Compilers durch, während der Kotlin-Compiler Ihren Code analysiert. Sie werden installiert, wenn Sie ihre Gradle-Plug-ins auf den Build anwenden.

Android SDK

Das Android SDK enthält die Android Platform und Java APIs für eine bestimmte Android-Version sowie die entsprechenden Tools. Mit diesen Tools können Sie das SDK verwalten, Anwendungen erstellen und mit Android-Geräten kommunizieren und diese emulieren.

Jede Version des Android SDK bietet bestimmte Java-APIs, auf die Ihr Quellcode zugreifen kann, sowie eine Unterstützung für die Desugarierung, um diese APIs unter früheren Android-Versionen zu verwenden.

JDK

Das Java Development Kit mit Java-Bibliotheken und ausführbaren Dateien, um den Java-Quellcode zu kompilieren und Java-Anwendungen auszuführen. Bei einem Android-Build werden mehrere JDKs verwendet. Weitere Informationen finden Sie unter Java-Versionen in Android-Builds.

Gradle-Bereiche

Gradle gruppiert Bibliotheksabhängigkeiten in verschiedene Bereiche (in der Gradle API als Konfigurationen bezeichnet), sodass Sie unterschiedliche Gruppen von Bibliotheksabhängigkeiten angeben können, die in verschiedenen Teilen Ihres Builds verwendet werden. Beispielsweise möchten Sie Testbibliotheken wie JUnit wahrscheinlich nicht in Ihre veröffentlichte Anwendung oder Bibliothek aufnehmen, aber beim Erstellen und Ausführen Ihrer Unit-Tests benötigen Sie sie. Außerdem können Sie mit Bereichen Symbol- oder Anmerkungs-Prozessoren hinzufügen, um Ihren Code zu analysieren.

AGP definiert beispielsweise die Bereiche implementation und api, mit denen Sie festlegen, ob eine Abhängigkeit Nutzern Ihres Unterprojekts zugänglich gemacht werden soll. Beschreibungen dieser und anderer Bereiche, die in einem Android-Build verwendet werden, finden Sie unter Abhängigkeiten konfigurieren.

Fügen Sie Bibliotheksabhängigkeiten im dependencies-Block Ihrer Build-Dateien entweder als group:artifact:version-Strings hinzu:

Kotlin

// In a module-level build script
// explicit dependency strings ("group:artifact:version")
dependencies {
    implementation("com.example:library1:1.2.3")
    api("com.example:library2:1.1.1")
}

Cool

// In a module-level build script
// explicit dependency strings ("group:artifact:version")
dependencies {
    implementation 'com.example:library1:1.2.3'
    api 'com.example:library2:1.1.1'
}

oder in einem Versionskatalog:

# Version catalog - gradle/libs.versions.toml
[versions]
exampleLib = "1.2.3"
examplePlugin = "2.3.4"

[libraries]
example-library = { group = "com.example", name = "library", version.ref = "exampleLib" }

[plugins]
example-plugin = { id = "com.example.plugin", version.ref = "examplePlugin" }

und geben Sie die generierten Variablen in Ihren Build-Dateien an:

Kotlin

// In a module-level build script
// Using a version catalog
plugins {
    alias(libs.plugins.example.plugin)
}

dependencies {
    implementation(libs.example.library)
}

Groovy

// In a module-level build script
// Using a version catalog
plugins {
    alias(libs.plugins.example.plugin)
}

dependencies {
    implementation libs.example.library
}