本文主要ProGuard的作用、使用及bug分析。
1、ProGuard作用
ProGuard通過删除無用代碼,将代碼中類名、方法名、屬性名用晦澀難懂的名稱重命名進而達到代碼混淆、壓縮和優化的功能,跟JavaScript的混淆壓縮類似。
壓縮和優化使得編譯後apk包更小。
混淆可以保證代碼在被反編譯後讀懂的難度很大,防止逆向工程。這點也是我們在應用釋出前需要ProGuard的一大原因。
2、ProGuard的使用
(1). 系統應用:
在項目根目錄下的Android.mk檔案中添加
XHTML
1
2
LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
LOCAL_PROGUARD_ENABLED := full
這樣應用不需要單獨設定proguard配置檔案,在系統編譯時會采用系統統一的proguard.cfg對該應用進行proguard,系統proguard.cfg位于系統根目錄\build\core内。
(2). 非系統應用:
a. 打開ProGuard開關
在項目根目錄下的project.properties檔案中配置proguard,添加如下代碼:
proguard.config=proguard.cfg
這樣在release模式下打包apk之前,proguard會以proguard.cfg為規則處理應用位元組碼。關于release模式下面第c部分會進行介紹
b. 編寫自己的proguard config檔案
預設會對所有代碼混淆,如果需要部分混淆,可以自己修改proguard.cfg檔案
注意下列類不能進行混淆:
(1)、反射用到的類
(2)、在AndroidManifest中配置的類(Activity、Service等的子類及Framework類預設不會進行混淆)
(3)、Jni中調用的類
c. 運作ProGuard及其生成的檔案介紹
在以release模式下打包apk時會自動運作ProGuard,這裡的release模式指的是通過ant release指令或eclipse project->android tools->export signed(unsigned) application package生成apk。在debug模式下為了更快調試并不會調用proguard。
如果是ant指令打包apk,proguard資訊檔案會儲存于<project_root>/bin/proguard檔案夾内;如果用eclipse export指令打包,會在<project_root>/proguard檔案夾内。其中包含以下檔案:
mapping.txt表示混淆前後代碼的對照表,這個檔案非常重要。如果你的代碼混淆後會産生bug的話,log提示中是混淆後的代碼,希望定位到源代碼的話就可以根據mapping.txt反推。
dump.txt描述apk内所有class檔案的内部結構
seeds.txt列出了沒有被混淆的類和成員
usage.txt列出了源代碼中被删除在apk中不存在的代碼
下圖為mapping.txt部分内容,以及混淆前後的代碼對比:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmLv91YwM2NmRTYkBDMfhTN0gDMwYjNzkzLcZDMzczLc12bj5icrNWasZ2YpRXY0NnL40mchZ2Lc9CX6MHc0RHaiojIsJye.jpg)
從中可以看出混淆後代碼大多abcdefg..
注意:養成儲存mapping.txt的習慣。ProGuard會在每次運作時覆寫原來的檔案,是以每次釋出請儲存mapping.txt,友善該版本出現問題時調出日志進行排查。mapping.txt可以根據版本号或是釋出時間命名來儲存或是放進代碼版本控制中。
d. ProGuard是否成功檢查
3、ProGuard混淆後bug分析
(1) 代碼本身bug
混淆後bug提示資訊中代碼都是混淆後代碼,類a. b. c…,如果需要排查,就得根據mapping.txt檔案去反推實際代碼中對應的代碼段進而解決問題
PS:混淆後代碼中的$表示匿名内部類,根據代碼中順序依次為OutClassName$1, OutClassName$2
(2) 因混淆而産生的bug
應用可能會因為ProGuard混淆了不該混淆的代碼而産生一些bug,其中最常見的就是ClassNotFoundException,還有BadParcelableException等
對于ClassNotFoundException,根據mapping.txt檔案反推找到某個類,然後在proguard.cfg中不進行混淆即可
Java
-keep class packagename.classname { *; }
對于android.os.BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called CREATOR,proguard.cfg中添加
3
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
對于android.support.v4 can’t find superclass or interface,can’t find referenced method,proguard.cfg中添加
4
-libraryjars libs/android-support-v4.jar
-dontwarn android.support.v4.**
-keep class android.support.v4.** { *; }
-keep interface android.support.v4.app.** { *; }