Android Studio(Gradle)解决库依赖冲突问题

最近在调整代码的时候,出现如下问题:

Cause: com.android.dex.DexException: Multiple dex files define Landroid/support/annotation/AnimRes;
    UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexException: Multiple dex files define Landroid/support/annotation/AnimRes;
        at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:579)
        at com.android.dx.merge.DexMerger.getSortedTypes(DexMerger.java:535)
        at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:517)
        at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:164)
        at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)
        at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:504)
        at com.android.dx.command.dexer.Main.runMonoDex(Main.java:334)
        at com.android.dx.command.dexer.Main.run(Main.java:277)
        at com.android.dx.command.dexer.Main.main(Main.java:245)
        at com.android.dx.command.Main.main(Main.java:106)

网上查询了一下,找到如下的解决方法:

我们常常用gradle.build文件导入依赖库,但是有时候库依赖会发生版本冲突或多个模块依赖同一个库的情况。

这就引出两个问题,如下:

  • 版本冲突时,Gradle会下载多个版本的依赖库吗?
  • 当多个模块依赖同一个库时,每个模块都会去下载该依赖库吗?
    为解决这疑问,接下来我们在Android StudioGradle举个例子:
    gradle.build依赖部分的配置:
dependencies {
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile ('com.android.support:design:22.2.1')
    compile 'com.shamanland:fonticon:0.1.8'
    androidTestCompile 'com.android.support:support-annotations:22.2.1'
    androidTestCompile 'com.android.support.test:runner:0.3'
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2')
}

在文件目录下或Android StudioTerminal下敲gradlew -q app:dependencies 命令,便有以下输出:

_debugAndroidTestApk - ## Internal use, do not manually configure ##
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- com.android.support.test:rules:0.3
     |    \--- com.android.support.test:runner:0.3 (*)
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- javax.annotation:javax.annotation-api:1.2
     \--- com.android.support.test:runner:0.3 (*)

_debugAndroidTestCompile - ## Internal use, do not manually configure ##
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- com.android.support.test:rules:0.3
     |    \--- com.android.support.test:runner:0.3 (*)
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- javax.annotation:javax.annotation-api:1.2
     \--- com.android.support.test:runner:0.3 (*)

_debugApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

_debugCompile - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

_debugUnitTestApk - ## Internal use, do not manually configure ##
No dependencies

_debugUnitTestCompile - ## Internal use, do not manually configure ##
No dependencies

_releaseApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

_releaseCompile - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

_releaseUnitTestApk - ## Internal use, do not manually configure ##
No dependencies

_releaseUnitTestCompile - ## Internal use, do not manually configure ##
No dependencies

androidJacocoAgent - The Jacoco agent to use to get coverage data.
\--- org.jacoco:org.jacoco.agent:0.7.4.201502262128

androidJacocoAnt - The Jacoco ant tasks to use to get execute Gradle tasks.
\--- org.jacoco:org.jacoco.ant:0.7.4.201502262128
     +--- org.jacoco:org.jacoco.core:0.7.4.201502262128
     |    \--- org.ow2.asm:asm-debug-all:5.0.1
     +--- org.jacoco:org.jacoco.report:0.7.4.201502262128
     |    +--- org.jacoco:org.jacoco.core:0.7.4.201502262128 (*)
     |    \--- org.ow2.asm:asm-debug-all:5.0.1
     \--- org.jacoco:org.jacoco.agent:0.7.4.201502262128

androidTestApk - Classpath packaged with the compiled 'androidTest' classes.
No dependencies

androidTestCompile - Classpath for compiling the androidTest sources.
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- com.android.support.test:rules:0.3
     |    \--- com.android.support.test:runner:0.3 (*)
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     +--- javax.annotation:javax.annotation-api:1.2
     \--- com.android.support.test:runner:0.3 (*)

androidTestProvided - Classpath for only compiling the androidTest sources.
No dependencies

androidTestWearApp - Link to a wear app to embed for object 'androidTest'.
No dependencies

apk - Classpath packaged with the compiled 'main' classes.
No dependencies

archives - Configuration for archive artifacts.
No dependencies

compile - Classpath for compiling the main sources.
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

可以看出:com.android.support.test:runner:0.3 这个模块原本是依赖于com.android.support:support-annotations22.2.0版本,但由于你又在gradle.build中加了这行androidTestCompile 'com.android.support:support-annotations:22.2.1'gradle就会下载com.android.support:support-annotations22.2.1版本,而不会去下载com.android.support:support-annotations22.2.0版本,因此com.android.support.test:runner:0.3 就会被强转变依赖于com.android.support:support-annotations22.2.1版本
第二个问题,我还是利用上面gradle命令行打出的信息来看看:

debugApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
|    +--- com.android.support:appcompat-v7:22.2.1 (*)
|    \--- com.android.support:support-v4:22.2.1 (*)
\--- com.shamanland:fonticon:0.1.8

仔细看上面的依赖,com.android.support:appcompat-v7:22.2.1com.android.support:design:22.2.1,有共同依赖一个com.android.support:support-v4:22.2.1库,且com.android.support:design:22.2.1 依赖于com.android.support:appcompat-v7:22.2.1,但从打印出的信息可以看出com.android.support:design:22.2.1 依赖两个库的信息被打了星号标记,这标记意思是忽略这两个依赖的意思,也就是说不去下载这两个库。
从上面的两个例子来看,gradle对于需要多个版本的依赖库来说,一般只会下载你配置导入那个版本,如果没有手动导入,那就会下载所有模块依赖的最新版本那个库,面对多个模块依赖同一个库,每个模块不都会去下载该依赖库,而是下载一个该依赖库,共享给多个模块。
修改配置文件为:

dependencies {
    compile 'com.android.support:appcompat-v7:22.2.1'
    compile ('com.android.support:design:22.2.1')
            {
                exclude group: 'com.android.support'
            }
    compile 'com.shamanland:fonticon:0.1.8'
    androidTestCompile 'com.android.support:support-annotations:22.2.1'
    androidTestCompile 'com.android.support.test:runner:0.3'
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2')
            {
                exclude  group:'com.android.support.test'
            }
}

打印信息:

$ gradlew -q app:dependencies

------------------------------------------------------------
Project :app
------------------------------------------------------------

_debugAndroidTestApk - ## Internal use, do not manually configure ##
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     \--- javax.annotation:javax.annotation-api:1.2

_debugAndroidTestCompile - ## Internal use, do not manually configure ##
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     \--- javax.annotation:javax.annotation-api:1.2

_debugApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

_debugCompile - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

_debugUnitTestApk - ## Internal use, do not manually configure ##
No dependencies

_debugUnitTestCompile - ## Internal use, do not manually configure ##
No dependencies

_releaseApk - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

_releaseCompile - ## Internal use, do not manually configure ##
+--- com.android.support:multidex:1.0.1
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

_releaseUnitTestApk - ## Internal use, do not manually configure ##
No dependencies

_releaseUnitTestCompile - ## Internal use, do not manually configure ##
No dependencies

androidJacocoAgent - The Jacoco agent to use to get coverage data.
\--- org.jacoco:org.jacoco.agent:0.7.4.201502262128

androidJacocoAnt - The Jacoco ant tasks to use to get execute Gradle tasks.
\--- org.jacoco:org.jacoco.ant:0.7.4.201502262128
     +--- org.jacoco:org.jacoco.core:0.7.4.201502262128
     |    \--- org.ow2.asm:asm-debug-all:5.0.1
     +--- org.jacoco:org.jacoco.report:0.7.4.201502262128
     |    +--- org.jacoco:org.jacoco.core:0.7.4.201502262128 (*)
     |    \--- org.ow2.asm:asm-debug-all:5.0.1
     \--- org.jacoco:org.jacoco.agent:0.7.4.201502262128

androidTestApk - Classpath packaged with the compiled 'androidTest' classes.
No dependencies

androidTestCompile - Classpath for compiling the androidTest sources.
+--- com.android.support:support-annotations:22.2.1
+--- com.android.support.test:runner:0.3
|    +--- com.android.support.test:exposed-instrumentation-api-publish:0.3
|    +--- junit:junit:4.12
|    |    \--- org.hamcrest:hamcrest-core:1.3
|    \--- com.android.support:support-annotations:22.2.0 -> 22.2.1
\--- com.android.support.test.espresso:espresso-core:2.2
     +--- com.android.support.test.espresso:espresso-idling-resource:2.2
     +--- com.squareup:javawriter:2.1.1
     +--- javax.inject:javax.inject:1
     +--- org.hamcrest:hamcrest-library:1.3
     |    \--- org.hamcrest:hamcrest-core:1.3
     +--- org.hamcrest:hamcrest-integration:1.3
     |    \--- org.hamcrest:hamcrest-library:1.3 (*)
     +--- com.google.code.findbugs:jsr305:2.0.1
     \--- javax.annotation:javax.annotation-api:1.2

androidTestProvided - Classpath for only compiling the androidTest sources.
No dependencies

androidTestWearApp - Link to a wear app to embed for object 'androidTest'.
No dependencies

apk - Classpath packaged with the compiled 'main' classes.
No dependencies

archives - Configuration for archive artifacts.
No dependencies

compile - Classpath for compiling the main sources.
+--- com.android.support:appcompat-v7:22.2.1
|    \--- com.android.support:support-v4:22.2.1
|         \--- com.android.support:support-annotations:22.2.1
+--- com.android.support:design:22.2.1
\--- com.shamanland:fonticon:0.1.8

比较上面两种配置compile信息部分,后面一种配置的 com.android.support:design:22.2.1 就没有输出两个打星号的依赖库信息了。
因此遇到这两种情况是,是gradle能自动帮我们解决掉了这两种情况,对于如何使用gralde命令行查看库依赖(depends)请看官方文档

参考链接


gradle 管理依赖库两个问题

发布者

《Android Studio(Gradle)解决库依赖冲突问题》上有4条评论

    1. 两者都可用,新建的工程都会生成gradlew.bat跟gradlew这两个文件的,如果是从Eclipse中转换过来的,可能没有这两个文件。本质上这两个文件还是调用了gradle -q app:dependencies

        1. 如果jar是放到libs目录下面的话,会导致这个jar被编译进项目,如果其他module也使用不同版本的jar包,那么会导致出现两份,最终会编译失败!如果是通过maven引入,Android Studio会自动使用更高版本的jar包。
          因此,一般建议都是使用maven来配置。

回复 panda 取消回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注