天天看點

ProGuard的作用、使用及bug分析

本文主要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部分内容,以及混淆前後的代碼對比:

ProGuard的作用、使用及bug分析

從中可以看出混淆後代碼大多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.** { *; }