「博客搬家」 原地址: CSDN 原发表时间: 2016-11-18
OkHttp 是一个流行的开源网络请求库。许多第三方库的底层都是使用 OkHttp 实现网络请求,所以 OkHttp 相关的依赖冲突问题就变得很难避免,下文是我所遇到的一次关于 OkHttp 的依赖冲突问题,通过对 Gradle 工具及 Android Studio 的灵活使用,解决了此问题。@H_403_5@
1. 关于 OkHttp 的依赖冲突
我的项目中, build.gradle 文件中设置的主要依赖:@H_403_5@
dependencies { compile 'com.android.support:appcompat-v7:24.0.0' compile 'cn.bmob.android:bmob-sdk:3.5.2' compile 'com.squareup.okhttp3:okhttp:3.4.2' compile 'com.facebook.fresco:imagepipeline-okhttp3:0.12.0' compile 'com.facebook.fresco:fresco:0.12.0' }
在写该 App 的过程中,出现了较为诡异的情况:@H_403_5@
- 使用 Run 'app' 命令可以在 Android 6.0「API 23」环境中成功运行 App
- 使用 Run 'app' 命令针对 Android 4.4「API 19」环境的虚拟机,进行 Gradle 构建时报错
- 使用「Generate Signed APK」,在进行 Gradle 构建时报错
- 在 cmd 或 Windows PowerShell 中执行如下 Gradle 指令:
gradle clean gradle build
Error:Error converting bytecode to dex: Cause: com.android.dex.DexException: Multiple dex files define Lokhttp3/Address; Error:Execution Failed for task ':app:transformClassesWithDexForDebug'. > com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException
:app:transformClassesWithDexForDebug Failed FAILURE: Build Failed with an exception. * What went wrong: Execution Failed for task ':app:transformClassesWithDexForDebug'. > com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: java.lang.Unsu pportedOperationException * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. BUILD Failed
通过打印的异常信息,可以确定问题是在于 OkHttp 的依赖冲突。@H_403_5@
2. 依赖冲突问题的探究
2.1 使用 Gradle 工具对依赖冲突进行探究
Gradle 相关简介:@H_403_5@
「一」Gradle位置:@H_403_5@
- C:Users< 用户名 >.gradlewrapperdistsgradle- < 版本号 > -all<一串识别码>gradle- < 版本号 >
- < Android Studio 目录 > gradlegradle- < 版本号 >
「二」Gradle 环境变量配置:@H_403_5@
此时,我直接使用 Gradle 工具检查此项目的依赖,进入项目目录,执行如下指令进行依赖检查:@H_403_5@
cd app gradle dependencies
打印出如下图所示的依赖树,依赖树显示了你 build 脚本声明的顶级依赖和它们的传递依赖:@H_403_5@
@H_403_5@
箭头所指的地方为与 OkHttp 相关的库,从依赖树可知,我自行引入的 OkHttp 库替换掉了 Fresco 中的低版本库,但仍旧提示依赖冲突。@H_403_5@
经过多次尝试,发现只有同时去掉这两个对 OkHttp 的依赖时,问题得到解决,build.gradle 文件修改如下:@H_403_5@
dependencies { compile 'com.android.support:appcompat-v7:24.0.0' compile 'cn.bmob.android:bmob-sdk:3.5.2' //compile 'com.squareup.okhttp3:okhttp:3.4.2' compile('com.facebook.fresco:imagepipeline-okhttp3:0.12.0',{ exclude module: "okhttp" }) compile 'com.facebook.fresco:fresco:0.12.0' }
2.2 对解决依赖冲突问题的尝试
这个问题很奇葩,去掉对 OkHttp 的依赖怎么可以呢?对着错误代码查遍了 Google 和 Stack Overflow,提到的解决方法有如下两条:@H_403_5@
2.2.1 使用 Multidex support library 开启 Multidex 功能
步骤 1:更改 build.grade@H_403_5@
defaultConfig { ... // Enabling multidex support. multiDexEnabled true } dependencies { ... compile 'com.android.support:multidex:1.0.1' }
步骤 2:设置 Application 类@H_403_5@
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); MultiDex.install(this); } }
步骤 3:更改 grade.properties@H_403_5@
org.gradle.jvmargs=-XX:MaxHeapSize\=2048m -Xmx2048m
2.2.2 通过增大可用内存解决「:app:transformClassesForDexForDebug」异常
在 gradle.build 中指定 javaMaxHeapSize:@H_403_5@
android { . . . dexOptions { javaMaxHeapSize "4g" //specify the heap size for the dex process } }
3. 追根溯源解决依赖冲突
3.1 问题的精确定位
通过中文搜索引擎搜索之后,在一篇文章中获得了灵感:@H_403_5@
对于如下异常:@H_403_5@
2.Execution Failed for task ':app:transformClassesWithJarMergingForDebug'. com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: android/support/v4/app/BackStackState$1.class原因:在所添加的 jar 包或 aar 包中也引用了 support-V4,与工程中引用的相冲突 @H_403_5@
Ctrl+N –> 在搜索框中输入 BackStackState –> 查找到所有引用该类的类,这些类即为引起冲突的类 @H_403_5@
去掉本工程中 gradle 中用于引用有冲突的包的代码或者将冲突的代码从 jar 包或 aar 包中移除,确保一个 module 中只引用了一份相同的第三方包@H_403_5@
Error:Error converting bytecode to dex: Cause: com.android.dex.DexException: Multiple dex files define Lokhttp3/Address;
由异常信息可知,OkHttp 下的 Address 类有冲突,执行如下步骤:@H_403_5@
- Ctrl + N
- 在搜索框中输入 Address
- 查找到所有引用该类的类
搜索到的内容,如下图所示。可知,Bmob 和 OkHttp 中均有该类。@H_403_5@
@H_403_5@
3.2 删掉冲突的 Jar 包
将项目的显示树由 Android 切换到 Project,查看 Bmob 的 Jar 包的结构,发现其中依赖了一个 OkHttp 的 Jar 包。@H_403_5@
@H_403_5@
由于使用了 Gradle 的远程依赖形式,故直接删除冲突的内容无效,须转为使用本地依赖的形式。@H_403_5@
根据 Bmob 官方文档的指示,删除 Bmob 的 Maven 仓库依赖,使用本地 Jar 包形式的依赖,去除对 OkHttp 的 Jar 包的引用,即可顺利解决问题。当然也可以只使用 Bmob 的远程依赖而在 build.gradle 中去掉其他相关「如 OkHttp,Gson,RxJava 等」的依赖。@H_403_5@
4. 参考资料
问题预备@H_403_5@
MultiDex@H_403_5@