gradle多工程打包衝突問題
將一個專案由eclipse轉android studio時,由於該專案引用lib多達6、7個,一上手就碰到了引用包衝突的問題,問題描述如下
UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexException: Multiple dex files define Landroid/support/v4/acce
ssibilityservice/AccessibilityServiceInfoCompat$AccessibilityServiceInfoVersionI
mpl;
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:50
4)
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)
雖然這個問題在網上有很多類似解決的帖子,但均說的不全面詳細,,我另外花了不少時間才把問題徹底解決,,在這裡把經驗分享出來。
第一步:
如果直接使用v4的jar包,gradle打包時,會將v4包打包進當前module,如果有引用該module的其它工程,會再將該module中的v4包再編譯一次,導致v4包被打包多次,引起衝突。在對應專案的build目錄下,你可以發現實實在在的存在多個v4包,只是它們的名字會多了一串sha1演算法生成的字串:
\build\intermediates\pre-dexed\official\debug
解決辦法:在build.gradle中加入compile ‘com.android.support:support-v4:23.1.0’並刪除libs目錄下的v4包,這樣可以避免多v4包的衝突問題(注意對應版本的V4包你是否下載,否則會另報錯):
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile 'com.android.support:support-v4:23.1.0'
}
如果第一步可以了,那恭喜你,下面的內容可以暫時忽略了(如果以後沒有包衝突的問題)。
但一般引用lib庫多,由eclipse轉的時候並不一定能這樣理想,所以如果還有衝突,請繼續看第二步。
第二步
既然還有衝突,那就去找到實際衝突的檔案是哪些。
首先開啟專案的root目錄,也就是專案資料夾同一級的目錄,會有一些gradle project的基本配置,目錄結構如下:
your project/
src/
res/
build/
build.gradle
settings.gradle
開啟build資料夾,定位到build\intermediates\dex-cache下,會有cache.xml這樣一個檔案。
它記錄了你的專案中所有依賴的庫的路徑、版本資訊、編譯後存入的路徑,如下:
<item
jar="C:\tfs\you project\libs\android-support-v4.jar"
jumboMode="false"
revision="23.0.2"
sha1="5896b0a4e377ac4242eb2bc785220c1c4fc052f4">
<dex dex="C:\tfs\your project\build\intermediates\pre-dexed\official\debug\android-support-v4_8d5ef003cbda980f7be9134c6bb7eb7a566626d2.jar" />
</item>
搜尋其中的android-support-v4.jar,這些即是多餘的引起衝突的包了,根據它提供的路徑,找到並刪除該jar。實際操作時,僅刪除jar是不夠的,由於gradle快取檔案的問題,上一次的編譯可能已經將jar在build目錄下編譯了對應的檔案,,所以直接將整個build目錄刪除了,避免快取帶來的刪除jar不生效的問題。
這樣再次編譯應該就能解決v4包衝突的問題了。
如果存在其它類似的引用衝突的問題(基本上帶Multiple dex的提示資訊都是同一個問題),,也可以直接開啟cache.xml,去定位問題。
gradle打包初次上手會有不少問題,,基本上找關鍵字build或gradle的目錄或檔案,分析一下應該會很容易找到解決方法。