How to Debug Which Dependency Adds a Specific Library or Class
Encountering a duplicate class error or an unexpected library in your Android project? A common culprit is a transitive dependency—a library that is automatically included by one of your direct dependencies. Thankfully, Gradle provides a powerful tool to investigate this: the dependency tree.
This guide will show you how to generate and read this tree to find the source of any problem library, like the common listenablefuture
conflict.
The Quick Command
The simplest way to see your project's dependency hierarchy is to run a command in the terminal.
Open the Terminal inside Android Studio (
View > Tool Windows > Terminal
).Run the following command:
./gradlew app:dependencies
This will output the entire dependency tree for your
app
module to the terminal.If your main module has a different name (e.g.,
myapp
), replaceapp
with that name:
./gradlew :myapp:dependencies
The Best Practice: Export to a File
The dependency tree can be very large and hard to read in the terminal. It's much more effective to export it to a text file for easy searching.
In the terminal, navigate to your project's root folder (if you aren't already there).
Run the command with a redirect to save the output to a file:
./gradlew app:dependencies > deps.txt
This will create a file named deps.txt
in your project's root directory.
How to Find the Problematic Dependency
Now that you have the deps.txt
file, you can easily search for the problematic library or class.
Open the
deps.txt
file in any text editor.Use the editor's Find function (Ctrl+F or Cmd+F).
Search for the name of the jar or dependency causing the error.
Example Searches:
For the common
ListenableFuture
conflict, search for:listenablefuture
For a duplicate class error, search for part of the class name or the jar file mentioned in the error message.
To find a specific library version, search for:
guava
orgson
The search results will show you all occurrences. Look at the indentation in the tree to see the hierarchy.
Reading the Tree
Dependencies are displayed in a tree structure. A +---
indicates a direct dependency, and subsequent |
and \---
symbols show transitive dependencies (libraries that your libraries depend on).
releaseRuntimeClasspath - Resolved configuration for runtime for variant: release +--- com.example:some-library:1.2.3 | \--- com.google.guava:listenablefuture:1.0 | \--- ... (further dependencies) \--- com.google.guava:guava:31.1-android
In this example, you can see that com.example:some-library:1.2.3
is pulling in the standalone listenablefuture:1.0
library, which could cause a conflict with the full guava
library.
What to Do Next
Once you've identified which dependency is bringing in the problematic library, you can solve the conflict by:
Excluding the Transitive Dependency: In your
app/build.gradle
file, you can exclude the specific module from the parent dependency.Aligning Versions: If different libraries require different versions of the same dependency, you can force a specific version using Gradle's dependency constraints.
By using the ./gradlew app:dependencies
command, you turn a frustrating build error into a solvable mystery, giving you complete control over your project's dependencies.
You may also find below article helpful:
Resolving "Duplicate Class ListenableFuture" Errors in Android Studio
Comments
Post a Comment