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 sulla risoluzione degli errori di risoluzione delle dipendenze che prevedono una logica di build personalizzata, consulta Strategie di risoluzione delle dipendenze personalizzate.

Visualizza le dipendenze del modulo

Alcune dipendenze dirette possono avere dipendenze proprie. Queste sono chiamate dipendenze transitive. Anziché dover dichiarare manualmente ogni dipendenza transitiva, Gradle le raccoglie e le aggiunge automaticamente. 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 della build, al set di origini di test e al percorso della classe. Di seguito è riportato un report di esempio per il classpath di runtime di un modulo dell'app della variante della build di debug e il classpath di compilazione del set di origine del test instrumentato.

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 > Tasks > 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 dell'utente di Gradle.

Escludi le dipendenze transitive

Man mano che l'ambito di un'app diventa più ampio, può contenere una serie di dipendenze, tra cui quelle dirette e transitive (librerie da cui dipendono le librerie importate dalla tua app). Per escludere le dipendenze transitive 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")
    }
}

trendy

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

Escludi le dipendenze transitive dalle configurazioni di test

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

Quindi, per escludere le dipendenze transitive dai tuoi test, devi farlo al momento dell'esecuzione, come illustrato di seguito:

Kotlin

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

trendy

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 dipendenze transitive per omettere le dipendenze transitive specifiche per la configurazione di test e che non sono incluse in altre configurazioni.

Correggi gli errori di risoluzione delle dipendenze

Quando aggiungi più dipendenze al progetto dell'app, queste ultime potrebbero entrare in conflitto tra loro. Il plug-in Android Gradle cerca di risolvere questi conflitti in modo agevole, ma alcuni conflitti potrebbero causare errori in fase di compilazione o di runtime.

Per aiutarti a capire quali dipendenze contribuiscono agli errori, controlla la struttura delle dipendenze dell'app e cerca eventuali dipendenze che appaiono più di una volta o con versioni in conflitto.

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

  1. Seleziona Naviga > Corso dalla barra dei menu.
  2. Nella finestra di dialogo di ricerca popup, assicurati che la casella accanto a Includi elementi non appartenenti al progetto sia selezionata.
  3. Digita il nome della classe visualizzato nell'errore di generazione.
  4. Ispeziona i risultati per verificare le dipendenze che includono la classe.

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

Correggere gli errori duplicati dei corsi

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

Program type already present com.example.MyClass

Generalmente questo errore si verifica a causa di una delle seguenti circostanze:

  • Una dipendenza binaria include una libreria che la tua app include anche 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 questo problema, rimuovi la Libreria B come dipendenza diretta.
  • La tua app ha una dipendenza binaria locale e una dipendenza binaria remota sulla stessa libreria.
    • Per risolvere questo problema, rimuovi una delle dipendenze binarie.

Risolvere i conflitti tra i percorsi delle classi

Una volta che Gradle risolve classpath di compile, prima risolve il classpath runtime e utilizza il risultato per determinare quali versioni delle dipendenze aggiungere al classpath di compile. In altre parole, classpath di runtime determina i numeri di versione richiesti per le dipendenze identiche dei classpath downstream.

Il classpath di runtime dell'app determina anche i numeri di versione richiesti da Gradle per la corrispondenza delle dipendenze nel classpath 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 visualizzati in più percorsi delle classi devono corrispondere in base a questa gerarchia.

Potrebbe verificarsi un conflitto in cui diverse versioni della stessa dipendenza appaiono su più percorsi di una classe quando, ad esempio, la tua app include una versione di una dipendenza che utilizza la configurazione delle dipendenze implementation e un modulo della libreria include una versione diversa della dipendenza utilizzando la configurazione runtimeOnly.

Quando risolvi le dipendenze dai classpath di runtime e tempo di compilazione, il plug-in Android Gradle 3.3.0 e versioni successive tenta di risolvere automaticamente alcuni conflitti tra le versioni downstream. Ad esempio, se il classpath del runtime include Library A versione 2.0 e il classpath di compile include la Library A versione 1.0, il plug-in aggiorna automaticamente la dipendenza di compile classpath alla Library A versione 2.0 per evitare errori.

Tuttavia, se il classpath del runtime include la Libreria A versione 1.0 e il classpath di compile include la Libreria A versione 2.0, il plug-in non esegue il downgrade della dipendenza del classpath di compile alla Libreria A versione 1.0 e viene comunque visualizzato 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 al modulo libreria. In altre parole, solo il modulo libreria dichiara la dipendenza, ma anche il modulo dell'app avrà accesso in modo transitivo alla sua API.
  • In alternativa, puoi dichiarare la dipendenza in entrambi i moduli, ma assicurati che ogni modulo utilizzi la stessa versione della dipendenza. Valuta la possibilità di configurare proprietà a livello di progetto per garantire che le versioni di ogni dipendenza rimangano coerenti in tutto il progetto.