Keywords: Android | Gradle | Dependency Conflict | Multiple dex files | Support Library
Abstract: This article provides an in-depth analysis of the common Multiple dex files define error in Android development, particularly focusing on the duplicate definition issue of Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompat caused by Android Support library version conflicts. Based on high-scoring Stack Overflow answers, the article systematically introduces methods for diagnosing dependency relationships using the gradle dependencies command, identifying conflict sources, and details the solution of excluding conflicting dependencies through the exclude module directive. Additionally, the article supplements other potential resolution strategies, such as adjusting dexOptions configuration, offering developers a comprehensive framework for problem-solving.
Problem Background and Error Analysis
During Android application development using Gradle for builds, developers may encounter the following error message:
UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dx.util.DexException: Multiple dex files define Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompat$AccessibilityServiceInfoVersionImpl;
at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:592)
at com.android.dx.merge.DexMerger.getSortedTypes(DexMerger.java:550)
at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:531)
at com.android.dx.merge.DexMerger.mergeDexBuffers(DexMerger.java:168)
at com.android.dx.merge.DexMerger.merge(DexMerger.java:186)
at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:300)
at com.android.dx.command.dexer.Main.run(Main.java:232)
at com.android.dx.command.dexer.Main.main(Main.java:174)
at com.android.dx.command.Main.main(Main.java:91)
This error indicates that during the build process, the Dex merging tool detected duplicate class definitions. Specifically, the class Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompat$AccessibilityServiceInfoVersionImpl is defined by multiple Dex files, causing the build to fail. From the error stack trace, it's evident that the problem occurs in the readSortableTypes method of com.android.dx.merge.DexMerger, which is a core component of Android build tools for handling Dex file merging.
Root Cause of Dependency Conflicts
By analyzing the build directory, two different versions of Support-v4 library files can be found:
Binary file build/pre-dexed/debug/support-v4-19.0.0-2ba5fdd60a6c3836b3104a863fe42897da1fa9d1.jar matches
Binary file build/pre-dexed/debug/support-v4-r7-227d905d79b23b20866531d4f700446c040a2ccb.jar matches
Although the project configuration only explicitly declares the compile 'com.android.support:support-v13:19.0.0' dependency, the Support-v13 library itself transitively depends on the Support-v4 library. The issue arises when other dependencies in the project introduce different versions of the Support-v4 library (such as the r7 version), leading to version conflicts. Such conflicts typically occur when third-party libraries use older or specific versions of the Support library.
Systematic Diagnostic Approach
The most effective method to accurately identify the source of dependency conflicts is to use Gradle's dependency analysis tool. Execute the following command in the project root directory:
gradle -q dependencies
Or for specific modules:
gradle -q :projectName:dependencies
This command generates a detailed dependency tree, showing all transitive dependencies. In the output, the source and version of each dependency can be clearly seen. For example, a structure similar to the following might be found:
compile - Classpath for compiling the main sources.
+--- com.commonsware.cwac:camera-v9:0.5.4
| +--- com.actionbarsherlock:actionbarsherlock:4.4.0
| | \--- com.google.android:support-v4:r7
| +--- com.commonsware.cwac:camera:0.5.4
| \--- com.android.support:support-v4:18.0.+ -> 18.0.0
\--- com.android.support:support-v4:18.0.+ -> 18.0.0
In this example, the com.commonsware.cwac:camera-v9:0.5.4 library transitively depends on com.google.android:support-v4:r7 through com.actionbarsherlock:actionbarsherlock:4.4.0, while the project itself directly depends on com.android.support:support-v4:18.0.+, resulting in a conflict between two different versions of the Support-v4 library.
Solution: Excluding Conflicting Dependencies
Once the source of the conflict is identified, Gradle's exclude directive can be used to exclude specific transitive dependencies. Here is a typical configuration example:
dependencies {
compile('com.commonsware.cwac:camera-v9:0.5.4') {
exclude module: 'support-v4'
}
compile 'com.android.support:support-v4:19.0.0'
}
In this configuration:
compile('com.commonsware.cwac:camera-v9:0.5.4')declares the dependency on the third-party libraryexclude module: 'support-v4'excludes the Support-v4 module transitively depended on by this librarycompile 'com.android.support:support-v4:19.0.0'explicitly specifies the Support-v4 version to be used by the project
After applying this configuration, running gradle -q dependencies again shows that the dependency relationships have been cleaned up:
compile - Classpath for compiling the main sources.
+--- com.commonsware.cwac:camera-v9:0.5.4
| +--- com.actionbarsherlock:actionbarsherlock:4.4.0
| \--- com.commonsware.cwac:camera:0.5.4
\--- com.android.support:support-v4:19.0.0
At this point, there is only one unified version of the Support-v4 library in the project, and the Multiple dex files define error is resolved.
Alternative Resolution Strategies
In addition to the method of excluding conflicting dependencies, other strategies can be attempted:
Adjusting Dex Options Configuration: Add the following configuration to the android block in the build.gradle file:
android {
dexOptions {
preDexLibraries = false
}
}
This configuration disables pre-Dex processing of libraries, which can sometimes avoid certain types of Dex merging conflicts. However, it should be noted that this may increase build time and is not effective in all cases.
Best Practices and Preventive Measures
To avoid similar dependency conflict issues, the following preventive measures are recommended:
- Regularly Check Dependency Relationships: Always run the
gradle dependenciescommand to inspect the dependency tree when adding new dependencies or updating existing ones - Unify Version Management: For core dependencies like Android Support libraries, try to maintain consistent versions throughout the project
- Use Dependency Constraints: In Gradle 5.0 and above, the
constraintsblock can be used to force specific dependency versions - Update Dependencies Promptly: Keep third-party libraries up to date, as newer versions typically resolve known compatibility issues
Through systematic diagnosis and appropriate solutions, the Multiple dex files define error can be effectively resolved. Understanding Gradle dependency management mechanisms and mastering the use of dependency analysis tools are essential skills for Android developers.