天天看點

Android使用ProGuard進行代碼混淆

使用proguard工具進行代碼優化和混淆, 以下是參考連結:

http://developer.android.com/tools/help/proguard.html

https://stuff.mit.edu/afs/sipb/project/android/sdk/android-sdk-linux/tools/proguard/docs/index.html#manual/introduction.html

http://blog.csdn.net/p106786860/article/details/11974863

在新版本的ADT建立項目時,混碼的檔案不再是proguard.cfg,而是project.properties和proguard-project.txt。

如果需要對項目進行全局混碼,隻需要進行一步操作:

将project.properties的中

“#  proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”的“#”去掉就可以了。

如果有一些代碼不能被混淆,比如需要加入了so檔案,需要調用裡面的方法,那麼調用JNI通路so檔案的方法就不能被混碼。在導出的時候,可能不會報錯。但是在手機上運作的時候,需要調用so檔案的時候,就會報某某方法無法找到。這個時候就需要用到proguard-project.txt。

在老版本中,建立項目的時候,會給出proguard.cfg,但是在的新版中建立項目則不會有任何提示。這個時候需要隻要将proguard.cfg的内容加入到proguard-project.txt中,再根據自己的需要進行編輯即可。

===============混淆檔案proguard.cfg詳解======================================

-injars  androidtest.jar【jar包所在位址】 

-outjars  out【輸出位址】

-libraryjars    'D:\android-sdk-windows\platforms\android-9\android.jar' 【引用的庫的jar,用于解析injars所指定的jar類】

-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

-keep public class com.android.vending.licensing.ILicensingService

-keep public abstract interface com.asqw.android.Listener{

public protected <methods>;  【所有方法不進行混淆】

}

-keep public class com.asqw.android{

public void Start(java.lang.String); 【對該方法不進行混淆】

}

-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 *;

}

=====================================常見異常===================================

參考:http://blog.csdn.net/vrix/article/details/7100841

加入第三方jar包之後常出現的幾個異常:

proguard returned with error code 1.See console

情況1:

Proguard returned with error code 1. See console 

Error: C:/Documents (系統找不到指定檔案) 

後來發現是因為将整個工程放到了桌面上,而桌面的目錄是C:/Documents and Settings/Administrator/桌面,在這裡面有空格,而proguard進行發編譯的時候是不允許有空格的

如果換了正确路徑還不好用的話,直接删除proguard就好了

注意:SDK和程式路徑最好不要有空格符

情況2:

Proguard returned with error code 1. See console 

異常:

java.lang.ArrayIndexOutOfBoundsException

解決辦法:将proguard.cfg中的"-dontpreverify"改成“-dontoptimize”

參考文章:http://groups.google.com/group/a ... ad/eca3b0f5ce6ad00f

我把項目中生成的proguard檔案夾(此時檔案夾是空的)删掉,然後再重新運作項目,就OK 了。

情況3:

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] Proguard returned with error code 1. See console

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] java.io.IOException: Can't read [[email protected]] (No such file or directory)

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] 

at proguard.InputReader.readInput(InputReader.java:230)

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] 

at proguard.InputReader.readInput(InputReader.java:200)

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] 

at proguard.InputReader.readInput(InputReader.java:178)

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] 

at proguard.InputReader.execute(InputReader.java:100)

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] 

at proguard.ProGuard.readInput(ProGuard.java:195)

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] 

at proguard.ProGuard.execute(ProGuard.java:78)

[2011-10-21 13:22:32 - ZMKSMarket_Build_v1.0] 

at proguard.ProGuard.main(ProGuard.java:499)

抛出這樣的異常的原因是第三方jar的引用路徑不對,沒有找到這個需要忽略混淆的jar包。

========================官方文檔翻譯========================================

原文

http://developer.android.com/guide/developing/tools/proguard.html

混淆器(ProGuard)

  在本文中(In this document)

Enabling ProGuard

Configuring ProGuard

Decoding Obfuscated Stack Traces

Debugging considerations for published applications

  參見

ProGuard Manual ?

ProGuard ReTrace Manual ?

混淆器通過删除從未用過的代碼和使用晦澀名字重命名類、字段和方法,對代碼進行壓縮,優化和混淆。結果是一個比較小的.apk檔案,該檔案比較難進行逆向工程。是以,當你的應用程式對安全敏感(要求高),例如當你 授權應用程式的時候,混淆器是一種重要的保護手段。 混淆器被內建在android 建構系統中,是以你不必手動調用它。同時混淆器僅在釋出模式下進行建構應用程式的時候才會運作起來,是以在調試模式下建構程式時,你不必處理混淆代碼。讓混淆器運作起來是可選擇的,但是推薦選上。 這個文檔描述了怎樣啟用并配置混淆器,以及使用跟蹤(retrace)工具對混淆的堆棧跟蹤資訊(stack traces)進行解碼。

啟用混淆器Enabling ProGuard當你建立了一個Android工程之後,一個 proguard.cfg檔案會在工程的根目錄下自動建立。這個檔案定義了混淆器是怎樣優化和混淆你的代碼的,是以懂得怎樣根據你的需要來定制是非常重要的。預設的配置檔案僅覆寫到了通常情況,是以根據你的需求,很可能需要編輯它。接下來的内容是關于通過定制混淆器配置檔案來對 混淆器配置。

為了讓啟用混淆器作為Ant或者Eclipse建構過程中一部分,可以在 <project_root>/default.properties檔案中,設定 proguard.config屬性。路徑可以是絕對路徑或者工程根目錄的相對路徑。

如果你讓 proguard.cfg檔案在預設位置(工程的根目錄),你可以像這樣指定位置:

proguard.config=proguard.cfg

     同樣,你可以把該檔案放到任意的位置,并指定它的絕對路徑。

proguard.config=/path/to/proguard.cfg

當你在釋出模式下,或者通過運作ant release,或者通過使用Eclipse中的Export Wizard建構你的應用程式的時候,建構系統都會自動地去檢查proguard.config屬性是否被設定了。如果被設定了,混淆器在把所有東西打包成.apk檔案之前,自動地對應用程式位元組碼進行混淆處理。而在調試模式中建構則不會調用混淆器,因為那樣調試會更加繁重。

      運作混淆器之後輸出的檔案有:

dump.txt

                   描述.apk包中所有class檔案的内部結構。

mapping.txt

列出了源代碼與混淆後的類,方法和屬性名字之間的映射。這個檔案對于在建構之後得到的bug報告是有用的,因為它把混淆的堆棧跟蹤資訊反翻譯為源代碼中的類,方法和成員名字。更多資訊,檢視解碼混淆過的堆棧跟蹤資訊。

seeds.txt

                   列出那些未混淆的類和成員。

usage.txt

                   列出從.apk中剝離的代碼。

這些檔案放在以下目錄中:

  • <project_root>/bin/proguard 當你使用Ant時
  • <project_root>/proguard 當你使用Eclipse時

注意:每次在釋出模式下建構時,這些檔案都會被最新的檔案覆寫。是以每次釋出程式時候,為了反混淆來自建構時産生的bug報告,請儲存這些檔案的一個拷貝。對于為什麼要儲存這些檔案的重要性的更多資訊,請檢視 程式釋出調試注意事項。

混淆器配置(proguard config) 某些情況下,proguard.cfg檔案的預設配置可以滿足需求了。但是,對于混淆器來說,大多數情況做出正确的分析是困難的,并且它或許會删除在它看來是無用的,但對于程式來說卻确實需要的代碼。一些例子如下:

  • 一個僅引用于AndroidManifest.xml檔案的類。
  • 一個通過JNI調用的方法。
  • 動态引用的屬性和方法。

預設的proguard.cfg檔案試圖覆寫普通的情況,但是你可能碰到類似ClassNotFoundException的異常,這個異常出現在當你的程式去通路一個被混淆器移除了的類的時候。

你可以在proguard.cfg檔案中添加-keep這一行來修複這些錯誤。例如: -keep publicclass<MyClass>

-Keep設定有很多可選項和注意地方,是以為了獲得更多關于配置資訊,強烈推薦你閱讀 混淆器使用者手冊。特别有用的有 Keep選項綜述和 舉例部分。在混淆器手冊 問題解決方案部分,介紹了代碼在混淆過程中你可能碰到的其他常見問題。 解碼混淆過的堆棧跟蹤資訊(Decoding Obfuscated Stack Traces)當混淆代碼并輸出了一個堆棧調試資訊時,這些方法名字是混淆過的,雖然可以進行調試,但是調試變得困難。幸運的是,每當混淆器運作時候,它都會輸出到檔案 <project_root>/bin/proguard/mapping.txt中,該檔案包含了從原始類,方法和屬性名字到混淆後名字的映射。

Windows系統中 retrace.bat腳本指令或者Linux和Mac OS X系統中 retrace.sh腳本指令能把混淆後的堆棧調試資訊轉換為可以了解的檔案。它被放在 <sdk_root>/tools/proguard/目錄下。運作 retrace工具的指令文法是:

retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]

例如: retrace.bat -verbose mapping.txt obfuscated_trace.txt

如果你沒有為 <stracktrace_file>指定值,那麼retrace工具從标準輸入讀取。

已釋出應用程式的調試注意事項(Debugging considerations for published applications)儲存好每一個已釋出給使用者的程式的 mapping.txt檔案。通過儲存釋出建構版本的 mapping.txt檔案拷貝,確定當使用者碰到bug,并把混淆後的堆棧調試跟蹤資訊送出給你時,你可以進行調試進而修複問題。程式的 mapping.txt檔案在每次釋出建構時都會被覆寫,是以你一定要注意儲存正确的版本。

例如,假設你已經釋出了一個應用程式并在繼續在新的版本中開發添加新的功能。接着你馬上啟動混淆器并建立一個新的釋出版本。該操作把 mapping.txt檔案覆寫了。一個使用者送出了來自目前釋出版本的bug報告,該報告包含了堆棧調試資訊。你再也不能對使用者的堆棧資訊進行調試了,因為這個對應使用者本機上版本的 mapping.txt檔案不存在了。其他覆寫 mapping.txt檔案的情況還有很多,是以對于每一個可能需要調試的版本,你都要確定有一份拷貝。

如何儲存mapping.txt檔案由你決定。例如,你可以根據版本和建構号來重命名它們,或者連同你的源代碼進行版本控制。