最近在调整代码的时候,出现如下问题:
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 Studio
用Gradle
举个例子:
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 Studio
的Terminal
下敲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-annotations
22.2.0版本,但由于你又在gradle.build
中加了这行androidTestCompile 'com.android.support:support-annotations:22.2.1'
故gradle
就会下载com.android.support:support-annotations
22.2.1版本,而不会去下载com.android.support:support-annotations
22.2.0版本,因此com.android.support.test:runner:0.3
就会被强转变依赖于com.android.support:support-annotations
22.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.1
和com.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 -q app:dependencies
两者都可用,新建的工程都会生成gradlew.bat跟gradlew这两个文件的,如果是从Eclipse中转换过来的,可能没有这两个文件。本质上这两个文件还是调用了gradle -q app:dependencies
如果一个modle中是通过jar导入的,是不是所有的都不去下载了,就用那个jar包了
如果jar是放到libs目录下面的话,会导致这个jar被编译进项目,如果其他module也使用不同版本的jar包,那么会导致出现两份,最终会编译失败!如果是通过maven引入,Android Studio会自动使用更高版本的jar包。
因此,一般建议都是使用maven来配置。