Eclipse與Android源碼中ProGuard工具的使用(代碼混淆)


由於工作需要,這兩天和同事在研究android下面的ProGuard工具的使用,通過查看android官網對該工具的介紹以及網絡上其它相關資料,再加上自己的親手實踐,算是有了一個基本了解。下面將自己的理解和認識簡要的做個筆記,有異議或者不解的,可以直接留言。

什么是ProGuard工具?


ProGuard是android提供的一個免費的工具,它能夠移除工程中一些沒用的代碼,或者使用語義上隱晦的名稱來重命名代碼中的類、字段和函數等,達到壓縮、優化和混淆代碼的功能。具體來說,使用ProGuard工具,可以達到下面兩個目的:

  • 刪除了源文件中沒有調用的那部分代碼,最大化的精簡了字節碼文件,使得最終生成的apk文件更小。
  • 使用語義混淆的命名替換了代碼中的類、字段和函數等,使得其他人無法反編譯獲取源代碼,起到對代碼的保護作用。

我看網上有不少人根據ProGuard工具的作用,直接稱呼其為“混淆代碼工具”,本文也暫時用這個詞簡稱。

更多的理解,可以參考ProGuard工具的官方文檔地址:http://developer.android.com/tools/help/proguard.html

ProGuard工具的集成與使用環境


其實,ProGuard工具是已經集成到我們android系統中的,所以不需要用戶手動的去集成。但是有一點需要注意,僅在程序處於Release模式時ProGuard才有效,反之在Debug模式是不能通過ProGuard來混淆代碼的。

根據ProGuard的具體使用環境,我分在Eclipse工具和android源碼兩種編譯環境淺談ProGuard的使用方法。

Eclipse環境中ProGuard的使用


以我電腦的android4.0環境為例,當我們在Eclipse中新建一個項目,或者導入一個已存在項目(保證當前項目沒有語法錯誤)后,在工程的根目錄,會自動生成兩個ProGuard的混淆文件:proguard-project.txt和project.properties(在老版本的ADT中,只會生成一個叫proguard.cfg的文件)。我們先看下文件project.properties :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

# Project target.
target=android-16

看后面一段注釋:To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home) ,意指要讓ProGuard 來壓縮和混淆代碼,把這句注釋去掉即可!所以,我們只要把下面一句注釋取消即可,如下所示:

1
2
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

我們仔細的看下這部分代碼:這個地方是通過設置proguard.config屬性來指定混淆代碼的配置文件為本機SDK目錄下面的proguard-android.txt文件,以及制定混淆的個性化配置文件為當前工程(eclipse下)根目錄下面的proguard-project.txt文件 ,而后面這個文件,恰是我們剛才看到的原本在根目錄下自動生成的另外一個文件!

其實打開了這個地方,我們就已經可以混淆代碼了,不過這里要注意:不能試圖通過運行eclipse中的Run as 和 Debug as 菜單來生成混淆代碼,必須通過如下圖所示的方法將apk導出才行,當然你可以選擇“簽名”或者“不簽名”:

圖片說明文字

這樣一步操作后,算是代碼混淆完成了。那么怎么才能檢驗我們真的混淆了代碼了呢?首先,我們能夠看到在工程的根目錄新生產了一個文件夾proguard,里面有四個文件,其內容如下:

  • dump.txt : 描述了apk中所有類 文件中內部的結構體。( Describes the internal structure of all the class files in the .apk file )
  • mapping.txt : 列出了原始的類、方法和名稱與混淆代碼見得映射。( Lists the mapping between the original and obfuscated class, method, and field names. )
  • seeds.txt : 列出了沒有混淆的類和方法。( Lists the classes and members that are not obfuscated )
  • usage.txt : 列出congapk中刪除的代碼。( Lists the code that was stripped from the .apk )

同時使用反編譯軟件對新生成的apk反編譯后會發現,里面的類名、方法和變量等,都變成了簡單的a、b、c、d等毫無含義的字母,這樣就達到了混淆的目的:
圖片說明文字

但在實際使用過程中,我們會發現當前apk中的有些方法和類,是要供外部使用的,而此時混淆了名稱,外部調用就會報錯了,那么怎么解決這個問題?此時就要用到我們剛才提到的混淆的個性化配置文件proguard-project.txt,在其中去配置不需要混淆的類、方法和變量等。關於混淆文件的具體配置方法,請看下面的最后一個標題會有詳述。

Android源碼環境中ProGuard使用


在Google發布的android源碼中,面對那么多代碼和文件目錄,此時該如何混淆代碼與配置混淆文件呢?

android中默認是將代碼混淆ProGuard關閉的,在alps/build/core/proguard.flags中有下面一句,意指將默認不混淆,不需要代碼刪除,我們將這一句注釋起來,就起到代碼混淆編譯的作用。

1
2
# Don't obfuscate. We only need dead code striping.
-dontobfuscate

可以說,這句是android工程中代碼混淆的總開關,然而,注釋了上面的代碼后,整個工程就已經是代碼混淆了嗎?不是的,這里還要關注一個文件alps/build/core/package.mk,在這個文件中有這么一段:

1
2
3
4
5
6
ifndef LOCAL_PROGUARD_ENABLED
ifneq ($(filter user userdebug, $(TARGET_BUILD_VARIANT)),)
    # turn on Proguard by default for user & userdebug build
    #LOCAL_PROGUARD_ENABLED :=full
endif
endif

切記:當我們需要對整個工程進行代碼混淆的時候,就把此處的 #LOCAL_PROGUARD_ENABLED :=full注釋去掉,成為有效的宏即可。如果不想對整個工程代碼混淆,而只是相對某個模塊混淆的話,就先不要動這里的代碼。

接着建議將真個工程new一遍,之后就可以針對具體的apk文件進行混淆文件的設置和定制了。下面以alps/packages/apps/Music為例說說該如何對特定模塊做到混淆代碼:

在Music目錄下,我們看到一個平時不太關注,但今天一定很在意的文件名:proguard.flags ,對了,這個文件就是Music的混淆配置文件,可以打開看看(有些地方沒有這個文件,用戶可以自己手動新建一下,最好名稱也叫proguard.flags,android下默認都是這個名字)。當然,設置了配置文件還是不夠的,還需要在同目錄的Android.mk中如下設置如下兩句:

1
2
LOCAL_PROGUARD_ENABLED  := full
LOCAL_PROGUARD_FLAG_FILES := proguard.flags

只有這樣才能讓混淆代碼有效,並且將混淆配置文件關聯起來。(有些模塊沒有這兩句句,就自己手動加上)

反之,如果用戶已經在alps/build/core/package.mk打開了全工程混淆編譯的控制點后,又在針對某個模塊時不想混淆編譯怎么辦?這就簡單了,將模塊下的Android.mk中設置為**LOCAL_PROGUARD_ENABLED := disabled**即可。

這樣,我們通過mm編譯后的代碼生成的apk,或者new真個工程后生成的燒機代碼,都是已經添加相應配置的混淆代碼了。

反編譯后,除過proguard.flags中定制的不需要混淆的代碼外,其他都是被混淆了,如圖所示是android中Music模塊的混淆后反編譯結果:

圖片說明文字

混淆文件的配置


在實際使用過程中,我們會發現當前apk中的有些方法和類,是要供外部使用的,而此時混淆了名稱,外部調用就會報錯了,那么怎么解決這個問題?此時就需要我們配置混淆的個性化文件proguard-project.txt(eclipse環境中)或者proguard.flags(android源碼環境),在其中去配置不需要混淆的類、方法和變量等。關於混淆文件的具體配置方法,大家可以去搜索下,我這里提供一段網上有人共享的配置代碼,這個配置代碼保留了工程文件中的Activity、Application、Service、BroadcastReceiver、ContentProvider、BackupAgentHelper、Preference和ILicensingService的子類,並保留了所有的Native變量名及類名,所有類中部分以設定了固定參數格式的構造函數,枚舉等等,用來防止外部調用出錯,大家可以借鑒下,以后來配置自己的文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference

 -keepclasseswithmembernames class * {
     native <methods>;
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM