由編譯一個android開源項目, 學習如何解決AndroidStudio編譯問題
關鍵字: android, studio, gradle, 編譯失敗, 編譯異常, appcompat-v7, 23.0.0
看過此文章能幫到你什么:
- 我在build.gradle里聲明的compile三方庫是什么規則.
- 我在build.gradle里聲明的compile三方庫, 具體內容下載到哪里去了.
- 編譯庫的時候的依賴到底是什么關聯關系.
- 三方庫下載下來了, 還出現出現編譯失敗問題, 怎么解決.
- 明明我配置的appcompat-v7版本是22.2.0(23.0.0以下), 編譯的時候怎么非給我弄成23.0.0(或以上).
- appcompat-v7總是編譯失敗, 怎么解決.
- 在Android-23(6.0)及以后不支持HttpClient了(沒有此API了), 我還要用這個庫, 不降級sdk, 該怎么辦.
- 解決編譯問題的思路.
開森的用git檢出一個github的好項目
,想學習學習別人的代碼,上來就給我報了個究極錯誤
!
項目地址:
一款基於Google Material Design設計開發的Android客戶端, 采取的是MVP架構開發.
如果項目已經更新, 編譯可能不按本文出錯. 可以用我fork的包含編譯錯誤的版本:
[僅用來學習使用]
1. 找不到對應的樣式資源:

把錯誤的原文貼到下邊! (貼這做啥子?
這不有圖嗎?..
) 為了方便被搜索爬蟲爬到, 爬蟲對我的截圖懶得識別(猜測). 希望遇到這種問題的童鞋能搜到這里.

E:\Samples\2015\StudioProjects11\SimplifyReader\library\build\intermediates\exploded-aar\com.android.support\appcompat-v7\23.0.0\res\values-v23\values-v23.xml
Error:(2)Error retrieving parent for item:No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'.
Error:(2)Error retrieving parent for item:No resource found that matches the given name 'android:Widget.Material.Button.Colored'.
Error:Execution failed for task ':library:processReleaseResources'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException:Process'command 'C:\Develop\studio\sdk\build-tools\22.0.1\aapt.exe'' finished with non-zero exit value 1
2. 對應的values-v23.xml被打開之后, parent的資源找不到, 如下(注意最上邊的文件)

就是這兩個, 分別在5行, 24行.
<stylename="Base.TextAppearance.AppCompat.Widget.Button.Inverse"parent="android:TextAppearance.Material.Widget.Button.Inverse"/>
<stylename="Base.Widget.AppCompat.Button.Colored"parent="android:Widget.Material.Button.Colored"/>
解決方案:
方案一: 降低v7的版本到23以下, 21或22都可以支持Material Design效果
方案二: 調高編譯版本到23及以上, 如果項目用到apache的HttpClient, 要單獨添加對其的支持
以下為方案一:
我們要解決問題, 更要知道為什么! 問題解決思路:
現在我們清楚問題在於appcomat-v7里的主題資源無法識別.
此時我們回看編譯配置文件build.gradle.
可以從Module(項目模塊)圖標上看的出來. 可運行項目是小手機圖標
, 庫項目是幾本書


當前項目有3個Module -> app(主項目), library(引用庫2), library_youku(引用庫2)
相對於Project目錄結構(看截圖標題), 以Android的目錄結構查看工程會更加直觀(目錄結構不深).


到底app有沒有引用其他兩個庫Module, 要看他app的build.gradle配置.
build.gradle配置:
app這里引用了其libs目錄下的所有jar, 兩個友盟的三方庫(首次需要聯網), 以及 library和library_youku兩個庫Module
注意:這里的配置也可以在窗口上方中間位置的
按鈕
查看.
(快捷鍵是
)



可以查看到對應配置界面:

這里並沒有配置appcompat-v7相關的內容.那可以大膽的確定, 一定在library或library_youku這兩個之中. (要不然還能配置到哪去?!)
打開library_youku的build.gradle:

library_youku這哥們配置的很少, 只有默認的libs和另一個庫項目:library.
(看名字
library_youku
猜也知道庫可能跟優酷相關, 名字越長, 功能越少嘛. 你自己感受一下: 哈佛大學, 哈爾濱機電數控模組工業職業技術培訓學院)
打開library的build.gradle:
這個時候我們毫不意外地看到了一個大型項目不可或缺的簡直喪心病狂到令人發指的一大堆引用庫:
注意后邊的注釋是專門給列位加的, 我是怎么認識這些庫的? 1.以前用過 2.我能在github搜到 3.我能在google,百度搜到.
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' // android官方support的v7包 compile 'com.android.support:cardview-v7:22.2.0'// android官方cardview-v7包, 給布局加個卡片式的背景. compile 'com.android.support:design:22.2.0' // android官方的material design風格包 compile 'com.jakewharton:butterknife:5.1.1' // 依賴注入框架butterknife, jakewharton大神作品 compile 'com.google.code.gson:gson:2.2.4' // json解析/序列化框架 compile 'me.gujun.android.taggroup:library:1.4@aar'// taggroup標簽組. 不知道什么鬼, 沒去搜 compile 'com.nineoldandroids:library:2.4.0'// 兼容3.0以前版本的屬性動畫庫,jakewharton大神良心之作 compile 'com.readystatesoftware.systembartint:systembartint:1.0.3' // 配置4.4.4及以上沉浸式狀態欄的庫. compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.3' // 經典的圖片異步加載緩存庫 compile 'com.github.chrisbanes.photoview:library:1.2.2'// 多點觸控放大縮小圖片的庫 compile 'com.afollestad:material-dialogs:0.7.9.1'// 材料化對話框庫 compile 'de.greenrobot:eventbus:2.4.0'// 事件總線庫 compile 'com.squareup.okhttp:okhttp:2.4.0'// 網絡數據加載庫(推薦) }
快速過了一遍, 里邊用到的網絡加載, 數據解析, 圖片處理庫都是比較流行的三方庫.
可是, 天殺的, 問題在於這里明明配置的是`
appcompat-v7:22.2.0
`而不是`
appcompat-v7:23.0.0
`
通過報錯的文件可以看到的確是
appcompat-v7\23.0.0 版本下的
\SimplifyReader\library\build\intermediates\exploded-aar\com.android.support\appcompat-v7\23.0.0\res\values-v23\values-v23.xml
可以看到我當前編譯的sdk版本是22

現在問題變成了兩個方向:
1. 怎么降低
appcompat-v7的版本為22.2.0 這樣就不會出現sdk22無法支持的資源.
2. 直接提升sdk編譯版本, 讓
appcompat-v7:23.0.0可以編譯通過.
方向一:
降低生成的appcompat-v7的版本為22.2.0, 不讓其出現無法識別的資源.
采用[折半查找]的戰略思想.
a. 把所有library的依賴全刪了b. 將臨時編譯目錄的下的所有文件刪了, 避免復用混淆: \SimplifyReader\library\build\intermediates\exploded-aar\c. 同步配置: 修改完配置后點右上角, 同步配置. 或屏幕上方中間
按鈕.
d. 思路: 相關的配置都刪了, 看你還生不生成23.0.0 , 如果不生成了, 肯定就是這里邊某個條目搞的鬼, 我再一半一半的刪除.![]()
果然
\SimplifyReader\library\build\intermediates\exploded-aar\
com.android.support下啥也沒有了, 編譯也不報那個錯了.
這不行, 有點過了. 然后再把編譯配置的后半部分刪了,如下:

此時一同步, 的確出現的只是
appcompat-v7/22.2.0而不是23.0.0
, 那么里邊也就不會出現
values
-
v23
.
xml
資源無法解析的問題了.
但是缺少了那些刪除的依賴, 項目肯定報錯找不着類.

此時分析: 問題一定出在剩下那個幾個庫中, 因為加了某個引用庫而導致v7包版本被強制提升. 經過把剩余的部分折半刪除. 可以定位到具體哪行配置出的問題. 一定要揪出你來!
有了思路, 一點一點來. 修改 -> 同步 -> 修改 -> 同步
果然, 找到了一行compile配置. 加了他,
同步后的
v7就提升為23.0.0, 不加他,同步后的v7 就還是我們配置的22.2.0
凶手就是他! 沒錯了:
compile 'com.afollestad:material-dialogs:0.7.9.1'
如果直接刪掉此庫, 代碼里也不使用, 項目即可正常運行. v7便是的是
22.2.0了. 但是就是一定要用呢?!
此時分析: 這個庫本身的依賴配置可能將v7的版本設置的比較高. 如果沒有配置文件, 怎么就平白無故因為你把我的整個項目v7版本提升了!
到jcenter找到這個庫的所有相關文件和資料:
庫中心網址:
http://jcenter.bintray.com/
分析當前依賴的寫法
1. com.afollestad:material-dialogs:0.7.9.1 是其在網站的定位方式
2. com.afollestad 表示其路徑, 或者包名, 工程名稱
3. material-dialogs 表示其工程下的項目/Module名稱
4. 0.7.9.1表示
material-dialogs項目的版本號
打開后我們可以看到如下內容

點開0.7.9.1可以看到里邊有如下內容:

.javadoc為其文檔包
.sources為其源碼包
.aar為開發引用庫 (用壓縮工具解壓即可看到內容)
.pom配置了該庫所依賴的其他庫
那么現在, 我要找到配置這個三方庫同步后, 我電腦到底把
這些東西
下載到哪里了!
誰可以告訴我?! 答: 一個全局文件搜索軟件: Listary, 或者Everything
搜什么? 搜0.7.9.1, 或者material-dialogs, 你要下載了文件名總不能隨機取一個吧...
果然有, 在C盤Users用戶目錄下, 可以看到路徑果然還包含了一些奇怪的生成的字符.

有三個關鍵的目錄, 繼續研究這三個目錄:
注意路徑里的
poplar是我的用戶名, 要改成自己的用戶名, 感概一下目錄好深.....
目錄1:
E:\Samples\2015\StudioProjects11\SimplifyReader\library\build\intermediates\exploded-aar\com.afollestad\material-dialogs\0.7.9.1
此目錄在工程項目的build文件夾中, 也就是說我們配置的compile
'com.afollestad:material-dialogs:0.7.9.1'
會在
build\intermediates\exploded-aar
目錄下保存其所有相關資源.
jars, res, 清單文件等.

目錄2:
C:\Users\poplar\.gradle\caches\modules-2\files-2.1\com.afollestad\material-dialogs\0.7.9.1
里邊有三個文件夾, 名字有一定的生成規則, 什么規則不重要:
分別保存了material-dialogs-0.7.9.1-sources.jar, material-dialogs-0.7.9.1.pom, material-dialogs-0.7.9.1.aar

剛才說到pom是保存的
material-dialogs庫的其他
依賴配置文件, 待會我們就要修改的是他了!!!
目錄3:
C:\Users\poplar\.gradle\caches\modules-2\metadata-2.15\descriptors\com.afollestad\material-dialogs\0.7.9.1
其中保存了編譯目錄2后的最終版本數據: 文件名為ivy.xml

接下來我們嘗試修改目錄2內部的
material-dialogs-0.7.9.1.pom,
可以看到這里果然保存了v7相關的依賴23.0.0, 因為都是support包的, 所以一並改成22.2.0
截圖如下:

然后重新同步編譯, 依舊報錯, 依舊是values-v23.xml里那兩個資源找不到, 也就是說
引用的仍舊是23.0.0版本
\SimplifyReader\library\build\intermediates\exploded-aar\com.android.support\appcompat-v7\23.0.0\
中仍舊是23.0.0的庫.
那我們改的.pom配置到底通過什么生效了呢?
此時打開目錄3里的文件:
ivy.xml
此文件中可以清楚的看到appcompat-v7對應的版本是23.0.0
這里也印證了我們之前配置時候的寫法com.afollestad:material-dialogs:0.7.9.1 -> org:name:rev -> 組織:名稱:版本號
此文件
ivy.xml並沒有在jcenter的目錄中出現過, 可以大膽猜想是在studio編譯時生成的臨時文件. 如果這個臨時文件刪了, 還可以重新生成.
我們的目的就是, 把所有出現23.0.0的, 全部搞成22.2.0 , 嗯, 就是這個原則! 就不信降不下來.
於是刪掉這個臨時生成的配置文件ivy.xml所在的根目錄.重新同步gradle


------------------------------振奮人心的時刻----------------------------------
同步通過了!
這個錯誤不報了!
但是!
但是!
項目里的代碼出了問題.
在項目的歡迎界面, 也就是SplashActivity里, 代碼參數錯誤:
需要的是Context和String
而代碼里只傳了個String過去, 我們在131行, 第一個參數加上this傳個context進去即可.

------------------------------振奮人心的時刻2!----------------------------------
重新同步
! 同步通過! 編譯通過! 運行通過!

冷靜, 回去看看發生了什么!
目錄3中的ivy.xml不出意外地變化了, rev都成了22.2.0

目錄1: 項目的build目錄中多出了22.2.0版本, 此時還保留了23.0.0. 如果把當前build目錄下全部刪除, 則仍舊會創建22.2.0目錄.

結論:
1. 類似com.afollestad:material-dialogs:0.7.9.1這樣的三方庫, 可以配置自己的三方依賴.
2. 這些依賴庫的三方依賴可以在material-dialogs-0.7.9.1.pom中手動修改. 重新同步可以生成ivy.xml, 從而降低整個項目的依賴版本
3. 當前Module最終使用的三方依賴, 如果build.gradle有重復配置. 取決於當前配置的所有庫中版本最高那個.
3. 當前Module最終使用的三方依賴, 如果build.gradle有重復配置. 取決於當前配置的所有庫中版本最高那個.
4. 做三方依賴庫的人最好把對其他依賴庫的版本調整到自己可用的最小版本. 以免使用者的依賴庫被
提升
.
5. 如果引用的三方依賴庫手動降級后, 如果該庫編譯失敗, 要么不用該庫, 要么提升項目sdk編譯版本.
吐槽:
1. 為什么作者不處理這個問題, 能直接編譯通過?
當前項目編譯版本設置的是
sdk22,
如果出現23.0.0的appcompat-v7庫肯定編譯不通過的, 因為沒有value-v23.xml對應的資源.
也就是說build文件中生成的可能就是配置的 compile 'com.android.support:appcompat-v7:22.2.0' 版本.他怎么生成的呢?
可能1: 作者的studio版本工具版本較低, 在低版本工具中不會自動提升依賴庫
可能2: 依賴庫
com.afollestad:material-dialogs:0.7.9.1在作者創作時的
material-dialogs-0.7.9.1.pom內配置的dependency版本在23.0.0以下.
我們在使用的時候, 去網上拿到的是更新后的內容.導致把整個v7版本提升.造成編譯失敗.我查看了
0.7.9.0版本, pom下配置的同樣是的23.0.0.
可能3: 作者的android support library版本太老, 沒有更新到23以后, 所以沒有自動提升到23.0.0. 截圖是我的更新后的庫


2. 為什么Google不考慮這個問題?
Google在每次你打開studio時, 都各種強烈建議升級studio, 升級sdk. 並不關心長城防火牆后的我們更新有多麻煩
不過近來國家防火牆好像已經給Android開發人員開了一道閘門, 用SDK Manager不用翻牆就能直接更新google主機的內容了.
更多:
畢竟修改配置文件的方式官方肯定不推薦, 要不然怎么把配置文件目錄藏得那么深.
不能每次都這么辦, 標准的做法應該是提升自己的sdk編譯版本為android-23 (6.0)及以上.
但是伴隨着compileSdkVersion編譯sdk版本和buildToolsVersion編譯工具版本提升, 伴隨着apache的HttpClient的無法調用.
下篇文章要解決的問題:
- 更新google的SDK及編譯工具.
- 配置了三方庫, 但下載不到三方庫時, 怎么解決.
- 在Android23及以后支持HttpClient的兩種方式.