關於 OkHttp 依賴衝突問題的解決過程

「博客搬家」 原地址: CSDN 原發表時間: 2016-11-18html

OkHttp 是一個流行的開源網絡請求庫。許多第三方庫的底層都是使用 OkHttp 實現網絡請求,因此 OkHttp 相關的依賴衝突問題就變得很難避免,下文是我所遇到的一次關於 OkHttp 的依賴衝突問題,經過對 Gradle 工具及 Android Studio 的靈活使用,解決了此問題。java

1. 關於 OkHttp 的依賴衝突

個人項目中, build.gradle 文件中設置的主要依賴:android

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 的過程當中,出現了較爲詭異的狀況:api

  • 使用 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
複製代碼

報錯,所報錯誤分別以下 :bash

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 的依賴衝突。網絡

2. 依賴衝突問題的探究

2.1 使用 Gradle 工具對依賴衝突進行探究

Gradle 相關簡介:app

「一」Gradle位置:jvm

  1. C:\Users< 用戶名 >.gradle\wrapper\dists\gradle- < 版本號 > -all<一串識別碼>\gradle- < 版本號 >ide

  2. < Android Studio 目錄 > \gradle\gradle- < 版本號 >工具

「二」Gradle 環境變量配置:

  1. 在環境變量裏添加用戶變量: GRADLE_HOME

  2. 在環境變量 path 中增長: %GRADLE_HOME%\bin;

此時,我直接使用 Gradle 工具檢查此項目的依賴,進入項目目錄,執行以下指令進行依賴檢查:

cd app
gradle dependencies
複製代碼

打印出以下圖所示的依賴樹,依賴樹顯示了你 build 腳本聲明的頂級依賴和它們的傳遞依賴:

依賴樹

箭頭所指的地方爲與 OkHttp 相關的庫,從依賴樹可知,我自行引入的 OkHttp 庫替換掉了 Fresco 中的低版本庫,但仍舊提示依賴衝突。

通過屢次嘗試,發現只有同時去掉這兩個對 OkHttp 的依賴時,問題獲得解決,build.gradle 文件修改以下:

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,提到的解決方法有以下兩條:

2.2.1 使用 Multidex support library 開啓 Multidex 功能

步驟 1:更改 build.grade

defaultConfig {
    ...
    // Enabling multidex support.
    multiDexEnabled true
}

dependencies {
    ...
    compile 'com.android.support:multidex:1.0.1'
}
複製代碼

步驟 2:設置 Application 類

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        MultiDex.install(this);
    }
}
複製代碼

步驟 3:更改 grade.properties

org.gradle.jvmargs=-XX:MaxHeapSize\=2048m -Xmx2048m
複製代碼

2.2.2 經過增大可用內存解決「:app:transformClassesForDexForDebug」異常

在 gradle.build 中指定 javaMaxHeapSize:

android {
    .
    .
    .
    dexOptions {
        javaMaxHeapSize "4g" //specify the heap size for the dex process
    }
}
複製代碼

不過,這兩種辦法都無益於解決問題。

3. 追根溯源解決依賴衝突

3.1 問題的精肯定位

經過中文搜索引擎搜索以後,在一篇文章中得到了靈感:

對於以下異常:

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 , 與工程中引用的相沖突

Ctrl+N –> 在搜索框中輸入 BackStackState –> 查找到全部引用該類的類,這些類即爲引發衝突的類

去掉本工程中 gradle 中用於引用有衝突的包的代碼或者將衝突的代碼從 jar 包或 aar 包中移除,確保一個 module 中只引用了一份相同的第三方包

根據這份解決思路,進行問題的最終解決。

首先獲取以下異常的關鍵信息:

Error:Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Lokhttp3/Address;
複製代碼

由異常信息可知,OkHttp 下的 Address 類有衝突,執行以下步驟:

  • Ctrl + N

  • 在搜索框中輸入 Address

  • 查找到全部引用該類的類

搜索到的內容,以下圖所示。可知,Bmob 和 OkHttp 中均有該類。

Address 類的搜索結果

3.2 刪掉衝突的 Jar 包

將項目的顯示樹由 Android 切換到 Project,查看 Bmob 的 Jar 包的結構,發現其中依賴了一個 OkHttp 的 Jar 包。

依賴的 Jar 包查詢

因爲使用了 Gradle 的遠程依賴形式,故直接刪除衝突的內容無效,須轉爲使用本地依賴的形式。

根據 Bmob 官方文檔的指示,刪除 Bmob 的 Maven 倉庫依賴,使用本地 Jar 包形式的依賴,去除對 OkHttp 的 Jar 包的引用,便可順利解決問題。固然也能夠只使用 Bmob 的遠程依賴而在 build.gradle 中去掉其餘相關「如 OkHttp,Gson,RxJava 等」的依賴。

4. 參考資料

問題預備

  1. Android OkHttp 徹底解析 是時候來了解 OkHttp 了
  2. Gradle 實戰「1」 - 配置環境變量
  3. Gradle 系列教程之依賴管理

MultiDex

  1. Android分包 MultiDex 原理詳解
  2. How to enable multidexing with the new Android Multidex support library

問題解決

  1. Android Studio 編譯中的一些問題解決辦法
  2. Android Studio 中如何解決重複依賴致使的 app:transformClassesWithJarMergingForDebug
  3. Bmob的開發文檔
相關文章
相關標籤/搜索