1. 程式人生 > >Eclipse打包Android專案時用到proguard.cfg後,出現的Warning:can't find referenced class問題的解決方案

Eclipse打包Android專案時用到proguard.cfg後,出現的Warning:can't find referenced class問題的解決方案

          這個看似簡單的問題困擾了我好久了,我已經google了很多相關的資訊了,但是在我看來總覺得他們說得不夠全面,包括官方的文件(ps:可能是我的英語瞭解能力不夠好^_^),好吧在這裡我就來個比較全面、嚴密一點的分析吧,希望能幫到遇到同樣問題的你,獻醜了:

1. 問題的產生原因

           "類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這個錯啊,打包不了!

          好,我們再看下去...

          接著他給我們舉個例子:如果ProGuard說它找不到javax.crypto class這個類,你可能還需要指定jce.jar包,緊接著還要指定更常用的rt.jar包。換句話說,javax.crypto class這個類裡面所引用到的類不但在jce.jar包裡面,還在rt.jar包裡面。

可是我專案中用到的所有第三方包都使用-libraryjars指定了呀!這個方法解決不了我的問題,不知道解決得了你的問題不?

          解決不了的話,再看下去...

          如果你缺少了某個庫,而且你絕對肯定自己沒有用到這個庫裡面的類的話,你可以試試你的運氣,使用-ignorewarnings或者-dontwarn選項!-dontwarn我試過了,加上
-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!而且程式能正確執行