Fehler bei der Behebung von Abhängigkeitsabhängigkeiten beheben

Wenn Sie eine Abhängigkeit hinzufügen, können Probleme mit Abhängigkeiten auftreten, die von der ursprünglichen Abhängigkeit benötigt werden, und Konflikte zwischen verschiedenen Abhängigkeitsversionen. Hier erfahren Sie, wie Sie Ihren Abhängigkeitsgraphen analysieren und häufige Probleme beheben.

Eine Anleitung zum Beheben von Fehlern bei der Abhängigkeitsauflösung, die benutzerdefinierte Buildlogik betreffen, finden Sie unter Strategien für die benutzerdefinierte Abhängigkeitsauflösung.

Fehler bei der Abhängigkeitsauflösung beheben

In diesem Prompt wird um Hilfe bei der Behebung von Abhängigkeitskonflikten gebeten.

Führen Sie diesen Prompt in Android Studio aus, während die Datei build.gradle geöffnet ist.

I'm getting the following error in my build: Conflict with dependency. Resolved versions for runtime classpath and compile classpath differ. What changes do I need to make to my dependencies to resolve this error.

KI-Prompts verwenden

KI-Prompts sind für die Verwendung in Gemini in Android Studio vorgesehen (aktuelle Canary-Version erforderlich).

Weitere Informationen zu Gemini in Studio finden Sie unter https://developer.android.com/studio/preview/gemini.

Modulabhängigkeiten ansehen

Einige direkte Abhängigkeiten können eigene Abhängigkeiten haben. Diese werden als transitive Abhängigkeiten bezeichnet. Anstatt dass Sie jede transitive Abhängigkeit manuell deklarieren müssen, werden diese von Gradle automatisch erfasst und hinzugefügt. Das Android-Plug-in für Gradle bietet eine Aufgabe, die eine Liste der Abhängigkeiten enthält, die Gradle für ein bestimmtes Modul auflöst.

Für jedes Modul werden im Bericht auch die Abhängigkeiten nach Buildvariante, Testquellensatz und Klassenpfad gruppiert. Im Folgenden finden Sie einen Beispielbericht für die Laufzeit-Classpath-Datei der Debug-Buildvariante eines App-Moduls und die Compile-Classpath-Datei des instrumentierten Test-Quellsatzes.

debugRuntimeClasspath - Dependencies for runtime/packaging
+--- :mylibrary (variant: debug)
+--- com.google.android.material:material:1.0.0@aar
+--- androidx.appcompat:appcompat:1.0.2@aar
+--- androidx.constraintlayout:constraintlayout:1.1.3@aar
+--- androidx.fragment:fragment:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
+--- androidx.recyclerview:recyclerview:1.0.0@aar
+--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
...

debugAndroidTest
debugAndroidTestCompileClasspath - Dependencies for compilation
+--- androidx.test.ext:junit:1.1.0@aar
+--- androidx.test.espresso:espresso-core:3.1.1@aar
+--- androidx.test:runner:1.1.1@aar
+--- junit:junit:4.12@jar
...

So führen Sie die Aufgabe aus:

  1. Wählen Sie Ansicht > Toolfenster > Gradle aus oder klicken Sie in der Toolfensterleiste auf Gradle .
  2. Maximieren Sie AppName > Aufgaben > android und doppelklicken Sie auf androidDependencies. Nachdem Gradle die Aufgabe ausgeführt hat, sollte das Fenster Ausführen geöffnet werden, um die Ausgabe anzuzeigen.

Weitere Informationen zum Verwalten von Abhängigkeiten in Gradle finden Sie im Gradle-Leitfaden unter Grundlagen der Abhängigkeitsverwaltung.

Transitive Abhängigkeiten ausschließen

Je größer eine App wird, desto mehr Abhängigkeiten kann sie enthalten, einschließlich direkter und transitiver Abhängigkeiten (Bibliotheken, von denen die importierten Bibliotheken Ihrer App abhängen). Wenn Sie transitive Abhängigkeiten ausschließen möchten, die Sie nicht mehr benötigen, können Sie das Keyword exclude verwenden, wie unten angegeben:

Kotlin

dependencies {
    implementation("some-library") {
        exclude(group = "com.example.imgtools", module = "native")
    }
}

Groovy

dependencies {
    implementation('some-library') {
        exclude group: 'com.example.imgtools', module: 'native'
    }
}

Transitive Abhängigkeiten aus Testkonfigurationen ausschließen

Wenn Sie bestimmte transitive Abhängigkeiten aus Ihren Tests ausschließen müssen, funktioniert das obige Codebeispiel möglicherweise nicht wie erwartet. Das liegt daran, dass eine Testkonfiguration (z.B. androidTestImplementation) erweitert die implementation-Konfiguration des Moduls. Das heißt, es enthält immer implementation-Abhängigkeiten, wenn Gradle die Konfiguration auflöst.

Wenn Sie also transitive Abhängigkeiten aus Ihren Tests ausschließen möchten, müssen Sie dies zum Zeitpunkt der Ausführung tun, wie unten gezeigt:

Kotlin

android.testVariants.all {
    compileConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp")
    runtimeConfiguration.exclude(group = "com.jakewharton.threetenabp", module = "threetenabp")
}

Groovy

android.testVariants.all { variant ->
    variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
    variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
}

Hinweis:Sie können das Keyword exclude weiterhin im Block „dependencies“ verwenden, wie im ursprünglichen Codebeispiel im Abschnitt Transitive Abhängigkeiten ausschließen gezeigt, um transitive Abhängigkeiten zu entfernen, die spezifisch für die Testkonfiguration sind und nicht in anderen Konfigurationen enthalten sind.

Fehler bei der Abhängigkeitsauflösung beheben

Wenn Sie Ihrem App-Projekt mehrere Abhängigkeiten hinzufügen, können diese direkten und transitiven Abhängigkeiten miteinander in Konflikt stehen. Das Android Gradle-Plug-in versucht, diese Konflikte möglichst reibungslos zu beheben. Einige Konflikte können jedoch zu Kompilierungs- oder Laufzeitfehlern führen.

Um herauszufinden, welche Abhängigkeiten zu Fehlern führen, prüfen Sie die Abhängigkeitsstruktur Ihrer App und suchen Sie nach Abhängigkeiten, die mehrmals oder mit abweichenden Versionen vorkommen.

Wenn Sie die doppelte Abhängigkeit nicht leicht finden können, können Sie über die Benutzeroberfläche von Android Studio nach Abhängigkeiten suchen, die die doppelte Klasse enthalten. Gehen Sie dazu so vor:

  1. Wählen Sie in der Menüleiste Navigation > Kurs aus.
  2. Achten Sie im Pop-up-Suchfeld darauf, dass das Kästchen neben Nicht zu Projekten gehörende Elemente einbeziehen angeklickt ist.
  3. Geben Sie den Namen der Klasse ein, der im Buildfehler angezeigt wird.
  4. Prüfen Sie die Ergebnisse auf Abhängigkeiten, die die Klasse enthalten.

In den folgenden Abschnitten werden die verschiedenen Arten von Fehlern bei der Abhängigkeitsauflösung beschrieben, die auftreten können, und wie Sie sie beheben können.

Fehler bei doppelten Kursen beheben

Wenn eine Klasse mehrmals im Laufzeit-Classpath erscheint, wird ein Fehler ähnlich dem folgenden angezeigt:

Program type already present com.example.MyClass

Dieser Fehler tritt in der Regel aus einem der folgenden Gründe auf:

  • Eine binäre Abhängigkeit umfasst eine Bibliothek, die auch in Ihrer App als direkte Abhängigkeit enthalten ist. Angenommen, Ihre App deklariert eine direkte Abhängigkeit von Bibliothek A und Bibliothek B, aber Bibliothek A enthält bereits Bibliothek B in ihrem Binärcode.
    • Um dieses Problem zu beheben, entfernen Sie Bibliothek B als direkte Abhängigkeit.
  • Ihre App hat eine lokale Binärdateiabhängigkeit und eine Remote-Binärdateiabhängigkeit von derselben Bibliothek.
    • Entfernen Sie eine der Binärabhängigkeiten, um das Problem zu beheben.

Konflikte zwischen Klassenpfaden beheben

Wenn Gradle den Compile-Classpath auflöst, wird zuerst der Classpath der Laufzeit aufgelöst und anhand des Ergebnisses wird ermittelt, welche Versionen von Abhängigkeiten dem Compile-Classpath hinzugefügt werden sollen. Mit anderen Worten: Der Laufzeit-Classpath bestimmt die erforderlichen Versionsnummern für identische Abhängigkeiten in Downstream-Classpaths.

Der Laufzeit-Classpath Ihrer App bestimmt auch die Versionsnummern, die Gradle zum Abgleichen von Abhängigkeiten im Laufzeit-Classpath für die Test-APK der App benötigt. Die Hierarchie der Klassenpfade ist in Abbildung 1 dargestellt.

Abbildung 1: Die Versionsnummern von Abhängigkeiten, die in mehreren Klassenpfaden vorkommen, müssen gemäß dieser Hierarchie übereinstimmen.

Ein Konflikt, bei dem verschiedene Versionen derselben Abhängigkeit in mehreren Klassenpfaden auftreten, kann beispielsweise auftreten, wenn Ihre App eine Version einer Abhängigkeit mit der implementation-Abhängigkeitskonfiguration und ein Bibliotheksmodul eine andere Version der Abhängigkeit mit der runtimeOnly-Konfiguration enthält.

Beim Auflösen von Abhängigkeiten in Ihren Laufzeit- und Kompilierungszeit-Classpaths versucht das Android Gradle-Plug-in 3.3.0 und höher, bestimmte Konflikte mit Downstream-Versionen automatisch zu beheben. Wenn der Laufzeit-Classpath beispielsweise Bibliothek A Version 2.0 und der Compile-Classpath Bibliothek A Version 1.0 enthält, aktualisiert das Plug-in die Abhängigkeit im Compile-Classpath automatisch auf Bibliothek A Version 2.0, um Fehler zu vermeiden.

Wenn der Laufzeit-Classpath jedoch Bibliothek A Version 1.0 und der Compile-Classpath Bibliothek A Version 2.0 enthält, führt das Plug-in nicht zu einem Downgrade der Abhängigkeit vom Compile-Classpath auf Bibliothek A Version 1.0. Sie erhalten weiterhin einen Fehler, der in etwa so aussieht:

Conflict with dependency 'com.example.library:some-lib:2.0' in project 'my-library'.
Resolved versions for runtime classpath (1.0) and compile classpath (2.0) differ.

Führen Sie einen der folgenden Schritte aus, um das Problem zu beheben:

  • Fügen Sie die gewünschte Version der Abhängigkeit als api-Abhängigkeit in Ihr Bibliotheksmodul ein. Das heißt, nur Ihr Bibliotheksmodul deklariert die Abhängigkeit, aber das App-Modul hat auch transitiven Zugriff auf die API.
  • Alternativ können Sie die Abhängigkeit in beiden Modulen deklarieren. Achten Sie jedoch darauf, dass jedes Modul dieselbe Version der Abhängigkeit verwendet. Sie können projektweite Eigenschaften konfigurieren, damit die Versionen der einzelnen Abhängigkeiten in Ihrem gesamten Projekt einheitlich bleiben.