這個看似簡單的問題困擾了我好久了,我已經google了很多相關的信息了,但是在我看來總覺得他們說得不夠全面,包括官方的文檔(ps:可能是我的英語瞭解能力不夠好^_^),好吧在這裏我就來個比較全面、嚴密一點的分析吧,希望能幫到遇到同樣問題的你,獻醜了:
"類1 can't find referenced class 類2" 字面上的意思就是類1找不到類2的引用;接着再看下去"You may need to specify additional library jars (using '-libraryjars').";
噢,原來這麼簡單呀,他說我需要使用-libraryjars加上項目中使用到的第三方庫就OK了。好!馬上把"-libraryjars ./libs/xx.jar"這段代碼加入到proguard.cfg配置文件裏面去,再export一次!一分鐘過後,靠!同樣的錯誤提示又來了:
- Warning: com.xxx.bbbb.F.H$3: can't find referenced class com.xxx.bbbb..F.H$com.xxx.bbbb.F.H$_B
- Warning: there were 1 unresolved references to classes or interfaces.
- You may need to specify additional library jars (using '-libraryjars').
- java.io.IOException: Please correct the above warnings first.
- at proguard.Initializer.execute(Initializer.java:321)
- at proguard.ProGuard.initialize(ProGuard.java:211)
- at proguard.ProGuard.execute(ProGuard.java:86)
- at proguard.ProGuard.main(ProGuard.java:492)
這不是坑爹嗎?還報錯!我以爲是順序不對,把-libraryjars ./libs/xx.jar這句話放到最開頭,或者在keep...語句的開頭,結果很悲催,也不行。馬上看看官方文檔的Troubleshooting,發現有說到這個問題後,大喜!我們一起去瞧瞧他怎麼說的:
- Warning: can't find superclass or interface
- Warning: can't find referenced class
- If there are unresolved references to classes or interfaces, you most likely forgot to specify an essential library.
- For proper processing, all libraries that are referenced by your code must be specified, including the Java run-time library.
- For specifying libraries, use the -libraryjars option.
- For example, if ProGuard complains that it can't find a javax.crypto class, you probably still have to specify jce.jar, next to the more common rt.jar.
- If you're missing a library and you're absolutely sure it isn't used anyway, you can try your luck with the -ignorewarnings option, or even the -dontwarn option. Only use these options if you really know what you're doing though.
- For example, if you're developing for Android, and ProGuard complains that it can't find a java.awt class, then some library that you are using is referring to java.awt.
- This is a bit shady, since Android doesn't have this package at all, but if your application works anyway, you can let ProGuard accept it with "-dontwarn java.awt.**".
2.官方對於這個問題的解釋:
如果存在未解決的類或者接口的引用的話,你很有可能忘記指定一些必要的庫了。正確的處理方法是在你代碼裏引用到的所有庫都必須要在配置文件中指定,包括Java運行庫,使用-libraryjars選項來指定這些庫。
看到這裏,你明白了剛剛爲什麼提示You may need to specify additional library jars (using '-libraryjars').了吧,目的就是在配置文件裏面加上項目中所使用到的第三方庫。可是,你這是坑爹呀,我明明給所有庫都加上-libraryjars參數指定了,結果還是報Warning: com.xxx.bbbb.F.H$3: can't find referenced class com.xxx.bbbb..F.H$com.xxx.bbbb.F.H$_B這個錯啊,打包不了!
好,我們再看下去...
可是我項目中用到的所有第三方包都使用-libraryjars指定了呀!這個方法解決不了我的問題,不知道解決得了你的問題不?
解決不了的話,再看下去...
-dontwarn com.xxx.bbbb.**之後確實沒有報錯,可以打包出來了!呵呵,別高興得太早,你拿你這樣打包好了的包去運行一下試試看?如果運氣好的話,程序沒有執行到找不到的類那裏就不會報錯,如果運氣不好的話執行到那裏了就會拋ClassNotFoundException!哼哼,怕了沒?
我們身爲備受矚目的程序猿,肯定要有職業道德的,總不能編譯出來的程序要使用到用戶的運氣+人品才能保證不出錯吧!!^_^
其實,我明白他說的意思的,就是說你要絕對確保這個類沒有被你的程序中使用到纔可以使用-ignorewarnings或者-dontwarn選項,接着,他又舉了個例子了: 比如你開發的是Android項目,但是打包時ProGuard抱怨找不到java.awt裏面的某些類,可能是因爲你使用的某些庫要用到java.awt包裏面的類,衆所周知,Android壓根就沒有java.awt這個包,它是J2SE裏面的包,我們Android程序當然不需要這個包也能很好的運行了,此時,你可以用-dontwarn java.awt.**來屏蔽掉所有關於java.awt的警告他舉這個例子是爲了說明一個理論:當你絕對確定自己的代碼沒有用到報錯的這個類後,可以使用-dontwarn com.xx.bbb**來屏蔽警告信息
3.總結出官方對於
Warning: can't find superclass or interface
Warning: can't find referenced class
這兩個問題的解決方法:
1.要把你項目中所引入的第三方jar包使用"-libraryjars 包路徑"指定好。2.還是報錯的話,確保報錯的類沒有在你的項目中使用到,使用"-dontwarn 類名正則表達式"屏蔽警告。
完了?可是我還想問:第一步做完後還是報錯,而且這個類在我項目中真的有用到,不能使用"-dontwarn .."屏蔽警告啊??
4.說了這麼久,終於開始說解決方案了:
其實找不到引用的這個類是第三方包裏面的,而且很多時候我們只需要打亂自己的代碼就行了,第三方包的代碼就是否要打亂就不要管了。嘻嘻,這叫做"只掃自己門前雪,甭管他人瓦上霜",
我們可以使用-dontwarn com.xx.bbb.**
-keep class com.xx.bbb.** { *;}
參數來保持第三方庫中的類而不亂,-dontwarn和-keep 結合使用,意思是保持com.xx.bbb.**這個包裏面的所有類和所有方法而不混淆,接着還叫ProGuard不要警告找不到com.xx.bbb.**這個包裏面的類的相關引用。
配置好後,重新打包,一切OK!而且程序能正確運行
-keepattributes Signature
#過濾註解
-keepattributes *Annotation*
-keep class **.R$*{*;}