Debug degli errori di risoluzione delle dipendenze

Quando aggiungi una dipendenza, potresti riscontrare problemi con le dipendenze richieste dalla dipendenza originale e conflitti tra le diverse versioni delle dipendenze. Ecco come analizzare il grafico delle dipendenze e risolvere i problemi comuni che si verificano.

Per indicazioni su come correggere gli errori di risoluzione delle dipendenze che coinvolgono la logica di compilazione personalizzata, consulta Strategie di risoluzione delle dipendenze personalizzate.

Eseguire il debug degli errori di risoluzione delle dipendenze

Questo prompt chiede aiuto per il debug dei conflitti di dipendenza.

Esegui questo prompt in Android Studio con il file build.gradle aperto.

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.

Utilizzare i prompt IA

I prompt AI sono destinati all'utilizzo in Gemini in Android Studio (è obbligatoria la versione Canary più recente)

Scopri di più su Gemini in Studio qui: https://developer.android.com/studio/preview/gemini

Visualizza le dipendenze dei moduli

Alcune dipendenze dirette potrebbero avere dipendenze proprie. Si tratta delle cosiddette dipendenze transitive. Anziché richiedere di dichiarare manualmente ogni dipendenza trasitiva, Gradle le raccoglie e le aggiunge automaticamente per te. Il plug-in Android per Gradle fornisce un'attività che mostra un elenco delle dipendenze risolte da Gradle per un determinato modulo.

Per ogni modulo, il report raggruppa anche le dipendenze in base alla variante di compilazione, al set di origine di test e al percorso di classe. Di seguito è riportato un report di esempio per il percorso di classe di runtime della variante di build di debug e il percorso di classe di compilazione del set di origine di test instrumentato di un modulo dell'app.

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
...

Per eseguire l'attività:

  1. Seleziona Visualizza > Finestre degli strumenti > Gradle (o fai clic su Gradle nella barra delle finestre degli strumenti).
  2. Espandi AppName > Attività > android e fai doppio clic su androidDependencies. Dopo che Gradle ha eseguito l'attività, dovrebbe aprirsi la finestra Esegui per visualizzare l'output.

Per ulteriori informazioni sulla gestione delle dipendenze in Gradle, consulta Nozioni di base sulla gestione delle dipendenze nella Guida utente di Gradle.

Escludere le dipendenze transitive

Man mano che l'ambito di un'app aumenta, può contenere una serie di dipendenze, tra cui quelle dirette e quelle transitive (le librerie da cui dipendono le librerie importate dell'app). Per escludere le dipendenze trasitive di cui non hai più bisogno, puoi utilizzare la parola chiave exclude come indicato di seguito:

Kotlin

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

Groovy

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

Escludere le dipendenze trascendenti dalle configurazioni di test

Se devi escludere determinate dipendenze traslative dai test, il codice di esempio mostrato sopra potrebbe non funzionare come previsto. Questo accade perché una configurazione di test (ad es. androidTestImplementation) estende la configurazioneimplementation del modulo. In altre parole, contiene sempre le dipendenze implementation quando Gradle risolve la configurazione.

Pertanto, per escludere le dipendenze trasitive dai test, devi farlo al momento dell'esecuzione, come mostrato di seguito:

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'
}

Nota: puoi comunque utilizzare la parola chiave exclude nel blocco delle dipendenze come mostrato nell'esempio di codice originale della sezione Escludi le dipendenze trascendenti per omettere le dipendenze trascendenti specifiche per la configurazione del test e non incluse in altre configurazioni.

Correggere gli errori di risoluzione delle dipendenze

Quando aggiungi più dipendenze al progetto dell'app, queste dipendenze dirette e traslative potrebbero essere in conflitto tra loro. Il plug-in Android Gradle versucht di risolvere questi conflitti in modo elegante, ma alcuni conflitti possono portare a errori di compilazione o di runtime.

Per aiutarti a esaminare le dipendenze che contribuiscono a generare errori, esamina l'albero delle dipendenze della tua app e cerca le dipendenze che appaiono più di una volta o con versioni in conflitto.

Se non riesci a identificare facilmente la dipendenza duplicata, prova a utilizzare l'interfaccia utente di Android Studio per cercare le dipendenze che includono la classe duplicata come segue:

  1. Seleziona Naviga > Classe nella barra dei menu.
  2. Nella finestra di dialogo di ricerca popup, assicurati che la casella accanto a Includi elementi non del progetto sia selezionata.
  3. Digita il nome della classe visualizzato nell'errore di compilazione.
  4. Esamina i risultati per verificare le dipendenze che includono il corso.

Le sezioni seguenti descrivono i diversi tipi di errori di risoluzione delle dipendenze che potresti riscontrare e come risolverli.

Correggere gli errori relativi ai corsi duplicati

Se una classe compare più di una volta nel percorso di classe di runtime, viene visualizzato un errore simile al seguente:

Program type already present com.example.MyClass

Questo errore si verifica in genere per una delle seguenti circostanze:

  • Una dipendenza binaria include una libreria inclusa anche nella tua app come dipendenza diretta. Ad esempio, la tua app dichiara una dipendenza diretta dalla libreria A e dalla libreria B, ma la libreria A include già la libreria B nel suo file binario.
    • Per risolvere il problema, rimuovi la libreria B come dipendenza diretta.
  • La tua app ha una dipendenza binaria locale e una dipendenza binaria remota dalla stessa libreria.
    • Per risolvere il problema, rimuovi una delle dipendenze binarie.

Correggere i conflitti tra classpath

Quando Gradle risolve il percorso di classe di compilazione, risolve prima il percorso di classe di runtime e utilizza il risultato per determinare quali versioni delle dipendenze devono essere aggiunte al percorso di classe di compilazione. In altre parole, il percorso di classe di runtime determina i numeri di versione richiesti per dipendenze identiche nei percorsi di classe a valle.

Il percorso di classe di runtime dell'app determina anche i numeri di versione richiesti da Gradle per la corrispondenza delle dipendenze nel percorso di classe di runtime per l'APK di test dell'app. La gerarchia dei classpath è descritta nella figura 1.

Figura 1. I numeri di versione delle dipendenze che compaiono in più percorsi di classe devono corrispondere in base a questa gerarchia.

Un conflitto in cui appaiono versioni diverse della stessa dipendenza in più percorsi di classe può verificarsi quando, ad esempio, la tua app include una versione di una dipendenza utilizzando la implementation configurazione della dipendenza e un modulo della libreria include una versione diversa della dipendenza utilizzando la configurazione runtimeOnly.

Quando risolvi le dipendenze nei classpath di runtime e compilazione, il plug-in Android Gradle 3.3.0 e versioni successive tenta di correggere automaticamente determinati conflitti di versione a valle. Ad esempio, se il percorso di classe di runtime include la versione 2.0 della libreria A e il percorso di classe di compilazione include la versione 1.0 della libreria A, il plug-in aggiorna automaticamente la dipendenza sul percorso di classe di compilazione alla versione 2.0 della libreria A per evitare errori.

Tuttavia, se il percorso di classe del runtime include la versione 1.0 della libreria A e il percorso di compilazione include la versione 2.0 della libreria A, il plug-in non esegue il downgrade della dipendenza sul percorso di compilazione alla versione 1.0 della libreria A e ricevi comunque un errore simile al seguente:

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.

Per risolvere il problema, esegui una delle seguenti operazioni:

  • Includi la versione desiderata della dipendenza come dipendenza api nel modulo della biblioteca. In altre parole, solo il modulo della libreria dichiara la dipendenza, ma anche il modulo dell'app avrà accesso alla sua API in modo transitivo.
  • In alternativa, puoi dichiarare la dipendenza in entrambi i moduli, ma devi assicurarti che ogni modulo utilizzi la stessa versione della dipendenza. Valuta la possibilità di configurare proprietà a livello di progetto per assicurarti che le versioni di ogni dipendenza rimangano coerenti in tutto il progetto.