ProGuard參數使用說明

ProGuard 使用說明

本文主要是翻譯proguad的官方文檔,以便以後使用的時候不需要再次去看英文,每次寫proguard總是那麼痛苦,必須寫個博客記錄一下,有些地方的意思我也不懂,有註明原文!!

什麼是proguard

proguard是一個用於對代碼進行瘦身,優化,混淆的java類庫,可以把沒有用到的方法,變量,屬性等自動移除,經過proguad處理的app,size會更小,運行更快,還可以增加反編譯的難度。

典型應用
  • 減少android app的size,加快啓動速度
  • 優化移動應用的代碼,提升性能
  • 保護app不被反編譯和篡改

proguard相比於其他java混淆工具的主要優勢是基於模板的配置(原文:compact template-based configuration)。一條簡單的命令就可以很有用。

proguard是一個命令行工具,也有圖形界面使用,還可以以插件的形式加入的ant,gradle等,它已經是android sdk的一部分,只需要簡單的配置就可以開啓(這點開發過android的苦逼都應該知道)。

proguad 使用代碼混淆來提供對反編譯的基本支持。但是還是可以被反編譯。如果需要深度的保護,需要使用 DexGuard。 DexGuard可以對app進行優化,混淆,還可以對string,classes,resource,resource files, asset files, and native libraries進行加密(看上去很牛逼的樣子,還沒有用過)

使用

進入正題,接下來學習各個命令的使用

運行proguard

java -jar proguard.jar options ...

可以在proguard發佈包的lib目錄下找到jar,也可以使用bin目錄下的腳本來運行,一般情況下可以把參數寫在 myconfig.pro中,然後運行

java -jar proguard.jar @myconfig.pro

也可以把腳本和參數合起來使用

java -jar proguard.jar @myconfig.pro -verbose

一個配置文件可以如下:

-injars       myapplication.jar 
-outjars      myapplication_out.jar 
-libraryjars  <java.home>/lib/rt.jar 
-printmapping myapplication.map 

-keep public class mypackage.MyMain { 
      public static void main(java.lang.String[]); 
}

接下來介紹各個參數

注:關於filename,class_path,filter的寫法後面有解釋

Input/Output Options

-include filename

遞歸的從給定文件中讀取參數

-basedirectory directoryname

指定當前配置文件中所有路徑參數的基本目錄

-injars class_path

指定需要被處理r的jar(或者 aars, wars, ears, zips, apks, or directories)。在默認情況下任何非.class的文件會被原樣複製到最終打包的jar。這裏需要注意的是那些臨時文件(如IDE產生的文件),尤其是當你直接用一個目錄指定jar文件。class_path下的條目可以被過濾,詳細請看filter,爲了可讀性,可以使用多條-injars命令

-outjars class_path

指定輸出jar包的名字(或者 aars, wars, ears, zips, apks, or directories)。前面-injars 指定的jar包會被包含到輸出jar包裏。這個也可以使用過濾,詳細請看filter
你必須避免讓輸出文件複寫輸入文件。爲了可讀性,可以使用多條-outjars ,如果沒有指定-outjar,不會有任何jar包生成。

-libraryjars class_path

指定要被處理的程序依賴的jar(或者 aars, wars, ears, zips, apks, or directories),這些jar不會被包進output jar。這個指定的jar至少得包含程序中有被繼承的類。那些只有被調用的庫中的class文件不需要出現,雖然他們的出現會改善優化的結果(什麼鬼, Library class files that are only called needn’t be present, although their presence can improve the results of the optimization step. )。當然這些path也是可以過濾的 ,爲了可讀性,可以使用多條 -libraryjars options.
請注意那些爲運行proguard設置的class path,不會被用於尋找類文件,也就是說你必須顯示的指定你的代碼需要用到的jar路徑。雖然這看上去有點麻煩,但是可以讓你處理不同運行環境下的程序。比如你可以處理
j2se 的程序也可以處理android app,只要你指定合適的jar路徑。

示例:

-injars       myapplication.jar 
-outjars      myapplication_out.jar 
-libraryjars  <java.home>/lib/rt.jar 
-printmapping myapplication.map 

-keep public class mypackage.MyMain { 
      public static void main(java.lang.String[]); 
}

-skipnonpubliclibraryclasses

在讀取依賴的庫文件時,略過非public類,來加快處理速度和減少ProGuard內存消耗 。

-dontskipnonpubliclibraryclasses

在讀取依賴的庫文件時,不要略過那些非public類,在4.5版本中,這是默認設置

-dontskipnonpubliclibraryclassmembers

不要忽略依賴庫中的非公有的類成員,包括域和方法,proguard默認會忽略

-keepdirectories [directory_filter]

指定那些需要被保留在輸出jar的文件目錄,在默認情況下,這些目錄會被移除來減小輸出文件的size。

-target version

指定需要被處理的類文件的java版本,如1.0, 1.1, 1.2, 1.3, 1.4, 1.5 (or just 5), 1.6 (or just 6), 1.7 (or just 7), or 1.8 (or just 8)

-keep 選項

指定需要被保留的類和成員。

-keepclassmembers

指定需要被保留的類成員,如果他們的類也有被保留。比如你要保留一個序列化類中的所有成員和方法

-keepclasseswithmembers

指定保留那些含有指定類成員的類,比如你想保留所有包含main方法的類

-keepnames

指定那些需要被保留名字的類和類成員,前提是他們在被代碼壓縮的時候沒有被移除。舉個栗子,你可能希望保留那些實現了Serializable接口的類的名字

-keepclassmembernames

指定那些希望被保留的類成員的名字

-keepclasseswithmembernames

保留含有指定名字的類和類成員。

下面介紹一下類名指定的語法,這部分也是最重要的,新手往往就死在這裏

首先看一下模板

[@annotationtype] [[!]public|final|abstract|@ ...] [!]interface|class|enum classname
    [extends|implements [@annotationtype] classname]
[{
    [@annotationtype] [[!]public|private|protected|static|volatile|transient ...] <fields> |
                                                                      (fieldtype fieldname);
    [@annotationtype] [[!]public|private|protected|static|synchronized|native|abstract|strictfp ...] <methods> |
                                                                                           <init>(argumenttype,...) |
                                                                                           classname(argumenttype,...) |
                                                                                           (returntype methodname(argumenttype,...));
    [@annotationtype] [[!]public|private|protected|static ... ] *;
    ...
}]

方括號 : []
方括號代表裏面的內容是可選的

省略號 : …
代表前面被指定的條目可以有任意多個。

豎線 : |
劃分兩個選項

括號 : ()
代表整體

縮進
用於說明意圖

空格
沒有意義

  • 關鍵字class 可以指向任何接口或類。interface 關鍵字只能指向接口,enum 只能指向枚舉 ,接口或者枚舉前面的!表示相對應的非枚舉或者接口。

  • 每個classname 都必須是全路徑指定,比如:java.lang.String 內部類使用美元符”$”分開,比如: java.lang.Thread$State 類名可以使用包含以下通配符的正則表達式:

    ? 任意匹配類名中的一個字符,但是不匹配包名分隔符。例如 “mypackage.Test?” 匹配”mypackage.Test1” 和 “mypackage.Test2”,不匹配 “mypackage.Test12”.

    *匹配類名的任何部分除了包名分隔符,例如”mypackage.*Test*”匹配 “mypackage.Test” 和 “mypackage.YourTestApplication”,但是不匹配 “mypackage.mysubpackage.MyTest”. 或者更通俗的講, “mypackage.*” 匹配所有 “mypackage”包裏的內容,但是不匹配它子包裏的內容.

    ** 匹配所有類名的所有部分,包括報名分隔符。

    • extendimplements 符號用於使用統配付來限定類. 他們效果是一樣的,指定只有繼承或者實現指定的類和接口。

    • @ 符號用於限定那些被指定註解符號標註的類和類成員,註解符的指定方法和類名一樣

    • 域和方法的指定更像java語言,除了方法參數中沒有參數名。表達式可以包含以下通配符:

    < init > 匹配任何構造函數

    < fields > 匹配任何域

    < methods > 匹配任何方法

    * 匹配任何方法和域

    注意: 上面的所有統配符都沒有返回值,只有< init >有參數列表.

    方法和域還可以用正則表示指定,可以使用的通配符如下:

    ? 任意匹配方法名中的單個字符

    * 匹配方法命中的任意部分

    數據類型描述可以使用以下通配符:

    % 匹配任何原生類型 (“boolean”, “int”, etc, but not “void”).

    ? 任意匹配單個字符

    * 匹配類名的任何部分除了包名分隔符

    ** 匹配所有類名的所有部分,包括報名分隔符。

    *** 匹配任何類型,包括原生和非原生,數組和非數組

    匹配任意參數個數
    ?* 和 ** 永遠不會匹配原生類型,而且只有 **** 匹配數組類型。舉個栗子:”** get*()” 匹配
    “java.lang.Object getObject()” 但是不匹配”float getFloat()” 也不匹配”java.lang.Object[] getObjects()”

  • 構造函數可以使用段類名(不包含包名)

  • 類訪問修飾符(public private static)一般用來限制統配類和類成員. 他們限定指定的類必須擁有指定的訪問修飾符.一個前置的!表示該修飾符沒有被設置

可以組合多個標誌 (e.g. public static). 表示兩個條件都要滿足

ProGuard 還支持一些的其他編譯器會用到的修飾符 synthetic, bridge, 和varargs.

-printseeds

將匹配的類和成員全部打印到文件或者輸出。這個可以用來驗證自己需要保留的類有沒有成功保留

Shrinking options

-dontshrink

不壓縮類文件。默認情況下會壓縮所有的類文件,除了那些用keep聲明和被這些類依賴的class

-printusage [filename]

將沒有用到的code打印到文件或者後臺

-whyareyoukeeping class_specification

將那些被保留的類的原因打印出來

Optimization options

-dontoptimize

不優化代碼,默認優化

-optimizations optimization_filter

指定需要被enable和disable的優化項目。

-optimizationpasses n

指定優化的pass數目,默認是1,多個pass可以提升優化效果. 如果在一個優化pass結束後,沒有發現被提升的項目,優化就結束

-assumenosideeffects class_specification

指定那些沒有任何副作用的方法,也就是說這些方法沒有實際用處,移除也沒關係,比如log方法,請謹慎使用該參數,除非你知道你在做什麼

-allowaccessmodification

設置該參數後,允許proguard在優化過程中擴大訪問權限。這樣可以提升優化效果。請不要講此選項應用在
作爲lib使用的code中,因爲這可能會將那些不希望被訪問的代碼變的可以被訪問

-mergeinterfacesaggressively

設置該參數後,允許interface被merge,即使他們的實現類沒有全部實現他們。這樣可以通過減少class的數量來減小輸出結果的size。java 二進制規範是允許這樣做的 (cfr. The Java Language Specification, Third Edition, Section 13.5.3), 雖然java語言不允許這樣做(cfr. The Java Language Specification, Third Edition, Section 8.1.4). 設置這個選項會在默寫虛擬機上降低處理的性能,因爲一些高級的JIT偏向於更少的類實現更多的接口,更壞的是,一些虛擬機可能無法處理被優化過的代碼。

Obfuscation options
(代碼混淆選項)

-dontobfuscate

不混淆代碼,默認混淆

-printmapping [filename]

將mapping 打印到文件或後臺

-applymapping filename

使用已有的mapping文件來混淆代碼

-obfuscationdictionary filename

指定希望被用做指定類和類成員混淆後新名字的列表

-classobfuscationdictionary filename

指定一個文件,裏面的所有名字將被用作混淆後類的名字

-packageobfuscationdictionary filename

指定一個文件,裏面的所有名字將被用作混淆後包的名字

-overloadaggressively

這隻這個選項後,多個方法和域會使用同一個名字,只要他們的參數和返回類型不一樣。這樣可以減少優化後的size

-useuniqueclassmembernames

如果類成員在混淆前擁有相同的名字,那麼混淆後也使用相同的名字,如果混淆前擁有不同的名字,那麼混淆後也是用不同的名字。如果不設置這個參數,那麼更多的成員可以被映射到同一個名字。如 ‘a’, ‘b’, 等。所以使用這個參數會稍微增加最後的size,但是這個可以確保被保存的混淆後的名字在後面的處理中被尊重。

-dontusemixedcaseclassnames

不生成大小寫混合的類名。在默認情況下,混淆後的類名會包含大小寫。但是當你在那些大小寫不敏感的平臺,比如windows下解壓混淆後的jar,解包工具會將那些相似名字的類複寫。

-keeppackagenames [package_filter]

不混淆指定的包名,包名用逗號分開。可以包含? * ,** 等通配符,也可以用!前置

-flattenpackagehierarchy [package_name]

將那些被重新命名的包重新打包,他們將會被移動到同一個父包裏。如果不指定包名或者是空字串,那麼他們會被打包到根包。

-repackageclasses [package_name]

將那些被重新命名的類重新打包,如果沒有指定參數或者是空字串,那麼包會被完全刪除。這個參數會覆蓋 -flattenpackagehierarchy參數。

-keepattributes [attribute_filter]

指定需要被保留的屬性,可以使用多條 -keepattributes命令。多條屬性用逗號分開,也可以使用? * ** 通配符,也可以使用!。例如,當你處理一個lib的時候至少得保留Exceptions, InnerClasses, and Signature 屬性。當你生成混淆stack traces時應該保留SourceFile 和LineNumberTable 。最後你可以保留annotations 如果你的代碼依賴他們。

-keepparameternames

保留那些需要被保留的方法的參數名字。這個選項事實上保留的是LocalVariableTable 和LocalVariableTypeTable這兩個debug屬性的修剪版本。這在處理lib的時候很有用。有些IDE可以用這些信息去協助開發者,比如工具提示和自動補全。

-renamesourcefileattribute [string]

指定一個放在類文件SourceFile 屬性的String。這些屬性必須放在開頭,所以這也必須用-keepattributes 顯示的指定。

-adaptclassstrings [class_filter]

指定那些對應到某個class name的String常量也要被混淆。如果沒有設置過濾,所有對應於某個class name的string都要被適配。如果有設置過濾,只適配匹配過濾的string。舉個例子,如果你的代碼中有大量對應class的硬編碼的string,然後你又不想保留他們的名字,就可以可以使用這個選項。

-adaptresourcefilenames [file_filter]

指定對資源文件重命名的時候,使用對應class被混淆後的名字。如果沒有指定過濾,所有資源文件都會被重命名,如果設置過濾,只有匹配的資源文件纔會被過濾

-adaptresourcefilecontents [file_filter]

指定內容需要被更新的資源文件。任何在這些資源文件中被提及的class name都要被重名,基於那些相應的類被混淆後的名字。如果沒有設置過濾,所有資源文件的內容將被更新。資源文件使用系統默認的字符集來解析和寫入。你可以通過設置環境變量 LANG或者java 系統屬性 file.encoding來更改。
警告: 你可能只希望將這個選項應用於text文件,因爲解析和適配二進制文件會導致一些意想不到的問題,所以請確保你的指定的file足夠精確.

Preverification options
(預校驗選項)

-dontpreverify

不對類文件進行預校驗。默認情況下,如果類文件的目標是Java ME或者不低於java 6,都會進行預校驗。
對於Java ME,預校驗是要求的,所以你需要運行一個外部的預校驗過程在你處理過的代碼上如果你設置了這個選項。對於 java 6 這是一個可選的選項,但是在java 7 這是被要求的。只有在andriod中這是不被強制要求的,所以你可以關閉這個選項。

-microedition

指定被處理的class file是指向Java ME的。這樣預校驗就會適當的添加StackMap屬性,這個和默認的StackMapTable屬性不一樣,因爲這是對於Java SE來說。

General options
(一般選項)

-verbose

在處理過程中輸出更詳細的信息,如果在處理過程中出現異常,將會輸出完整的調用棧,而不是隻有錯誤信息

-dontnote [class_filter]

不要輸出配置文件的潛在錯誤和遺漏,比如類名拼寫錯誤或者缺少一些有用的選項。可選的過濾器是一個正則表達式;ProGuard 不會打印那些被過濾器匹配成功的類名的信息。

-dontwarn [class_filter]

完全不要警告unresolved references 和 其他重要的問題.可選的過濾器是一個正則表達式。 ProGuard 不會打印那些被過濾器匹配的成功的類的警告信息。忽略警告是非常危險的,舉個例子,如果 unresolved classes or class members是確實被需要的,那麼代碼可能無法正常工作,所以請小心使用

-ignorewarnings

打印任何關於unresolved references 和其他重要問題的警告,但是會繼續處理下去。忽略警告是危險的。舉個例子如果 unresolved classes or class members是確實被需要的,那麼代碼可能無法正常工作,所以請小心使用

-printconfiguration [filename]

將配置文件的內容,包括被替換的變量和引入的文件打印到後臺或者文件。

-dump [filename]

在任何處理步驟後,輸出類文件的內部結構。可以輸出到後臺或者文件。比如,你可能希望打印出一個jar包的所有內容。

Class paths
(類路徑)

ProGuard 接受一個通用的類路徑來表示輸入文件和輸出文件。一個類路徑可以有好幾個類組成,由分隔符分開 (e.g. ‘:’ on Unix, or ‘;’ on Windows platforms),出現順序決定 了在出現重複類時候的優先級。

輸入文件和輸出文件可以是以下形式:

  • 類文件或資源文件
  • apk
  • jar
  • aar
  • war
  • ear
  • zip
  • 目錄

直接指定的類文件和資源的路徑會被忽略,所以類文件應該是一個jar ,aar, a war, ear, zip, 或者目錄的一部分。另外,類路徑應該沒有額外的前綴。

關於在打包的時候的選項,可以參考一下例子

restructure output archives.

關於文件和目錄的命名可以參考file names

另外 ProGuard還可以基於類文件的完整相對名字來過濾類路徑和他們的內容。每個類路徑可以被最多7個文件過濾器跟着,這些過濾器用圓括號括起來,並用分號分開:

  • 用於aar的過濾器,
  • 用於apk 的過濾器,
  • 用於zip 的過濾器,
  • 用於ear 的過濾器,
  • 用於war 的過濾器,
  • 用於jar 的過濾器,
  • 用於所有類文件名和資源文件名的過濾器.

如果少於7個過濾器被指定,他們會被認爲是後者的過濾器。任何空的過濾器會被忽略。更正式,一個被過濾的class path可以如下:

classpathentry([[[[[[aarfilter;]apkfilter;]zipfilter;]earfilter;]warfilter;]jarfilter;]filefilter)

方括號的意思是裏面的內容是可選的

例如, “rt.jar(java/.class,javax/.class)” 匹配rt.jar中所有在java和javax目錄下的class文件

例如, “input.jar(!.gif,images/)” 匹配在input.jar裏images目錄下所有文件,除了.gif文件

不同的過濾器會被應用到所有相應的文件類型,不管他們在jar中的嵌套層次;他們是正交的(orthogonal)

例如, “input.war(lib/.jar,support/.jar;.class,.gif)” 只關注input war 裏lib目錄下的jar和suppor目錄下的jar,然後會匹配所有遇到的class文件和gif文件

File names

ProGuard 接受文件和目錄的絕對路徑和相對路徑。相對路徑的解釋如下:
如果設置了基準目錄,則就相對基準目錄,否則就相對與配置文件的路徑,其他任何情況就相對與工作目錄。名字可以包含java系統屬性(或者Ant 屬性,如果使用Ant),用’<’和’>’分隔。屬性會被自動替換成他們對應點值。

那些帶有特殊字符的名字像空格和括號,必須用單引號或者雙引號括起來。每個在列表中的名字必須用引號單獨的括起來。引號本身需要escaped 當使用命令行的時候,來避免被shell gobbled。

例如,在命令行,你可以使用’-injars “myprogram.jar”:”/your directory/your program.jar”’

File filters

像通用過濾器,文件過濾器是一個包含通配符,用逗號分開的名字列表。只有名字匹配了過濾的的文件纔會被讀取或者寫入。支持以下通配符:

? 匹配任何單個字符
* 匹配文件名的任何部分,除了路徑分隔符
** 匹配文件名的任何部分,包含任意個文件分隔符

例如, “java/.class,javax/.class” 匹配所有在java和javax裏的class文件。

此外, 文件名字之前可以加!,表示排除這個文件名

例如,”!**.gif,images/**”匹配所有在images目錄下除了gif文件之外的所有文件

Filters

ProGuard提供了很多帶有過濾器的選項,在配置的各個方面:文件名,目錄,類,包,屬性,優化等。 過濾器是包含了一串用逗號分開的含有通配符的名字列表。只有匹配的名字纔可以通過過濾器。支持的通配符依賴於那些被過濾名字的類型,但是以下的通配符是典型的:
A filter is a list of comma-separated names that can contain wildcards. Only names that match an item on the list pass the filter. The supported wildcards depend on the type of names for which the filter is being used, but the following wildcards are typical:

? 匹配任何單個字符
* 匹配文件名的任何部分,除了路徑分隔符

此外, 名字還可以用!做前綴來用於在後面的匹配中將該名字排除。所以一個名字如果匹配一個過濾器,它是被拒絕或者接受取決於那個過濾器的條目是不是以!開頭。如果名字不匹配這個過濾條目,就繼續匹配接下來的條目。如果不匹配任何個條目,它是被拒絕還是接受要取決於最後的過濾條目是否以!開頭

例如, “!foobar,*bar” 匹配所有以bar結尾的名字,除了footbar。

Keep option modifiers

includedescriptorclasses

如果某些方法和域被-keep保留,那麼這些方法和域的類型描述符中的任何類也要被保留。這在保留native方法名字時很有用,用來確保native方法的參數類型不會被重命名。

allowshrinking

指定被-keep保留的條目可以被壓縮,即使他們不得不被保留。意思是,條目可能在壓縮步驟中被移除,但是如果他們是必須的,他們可以不被優化或者混淆。

allowoptimization

指定被-keep的條目可以被優化,即使他們必須被保留。意思是條目可能在優化步驟中被改變,但是他們可以不被移除或者混淆。

allowobfuscation

指定被-keep的條目可以被混淆,即使他們必須被保留。意思是,條目可能在混淆步驟中被改名,但是他們可以不被移除和優化。

Overview of keep options

各種各樣的用於壓縮和混淆的-keep選項 在剛開始可能讓人感覺混亂,但是卻是有規律的。下表羅列了他們之間的關係:

Keep From being removed or renamed From being renamed
Classes and class members -keep -keepnames
Class members only -keepclassmembers -keepclassmembernames
Classes and class members, if class members present -keepclasseswithmembers -keepclasseswithmembernames

每一個-keep 選項後面會跟着一個類和類成員的定義,-keep將被引用到這些類和類成員中。

如果你不確定你需要哪一個選項,你應該簡單的使用-keep。它會確保指定的類好成員不會在壓縮步驟中被移除,和在混淆步驟中被改名。

如果你指定類的時候沒有指定類成員,ProGuard只會保留類和它的無參構造函數。

如果你指定了一個方法,ProGuard只會保留這個方法,它的代碼任然會被優化和適配。

在android中的應用

Android activity

-injars      bin/classes 
-outjars     bin/classes-processed.jar 
-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar 

-dontpreverify 
-repackageclasses '' 
-allowaccessmodification 
-optimizations !code/simplification/arithmetic 
-keep public class mypackage.MyActivity 

一個完整的Android程序

標準的Android SDK build過程已經整合了Proguard(with Ant, Gradle, Android Studio and Eclipse).你只要將project.properties中的“proguard.config=…..”註釋去掉就可以。

Notes:

  • 一旦遇到問題,你可能想要檢查一下配置文件.

  • Android SDK revision 20 和後面的版本在配置文件的開啓proguad上有一點區別, ${sdk.dir}/tools/proguard/proguard-android-optimize.txt 代替默認的 ${sdk.dir}/tools/proguard/proguard-android.txt.

  • 編譯過程已經設置了必要的jar,輸入jar和輸出jar,不需要再次設置.
    -如果你看到關於missing referenced classes的警告:這太常見了,你可以看看 Troubleshooting shooting部分。

如果你正在從scratch構建編譯過程:這些選項會壓縮,優化,混淆編譯過的classes和外部依賴庫的所有public activities, services, broadcast receivers and content providers:

-injars      bin/classes 
-injars      libs 
-outjars     bin/classes-processed.jar 
-libraryjars /usr/local/java/android-sdk/platforms/android-9/android.jar 

-dontpreverify 
-repackageclasses '' 
-allowaccessmodification 
-optimizations !code/simplification/arithmetic 
-keepattributes *Annotation* 

-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.view.View { 
      public <init>(android.content.Context); 
      public <init>(android.content.Context, android.util.AttributeSet); 
      public <init>(android.content.Context, android.util.AttributeSet, int); 
      public void set*(...); 
} 

-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.content.Context { 
    public void *(android.view.View); 
    public void *(android.view.MenuItem); 
} 

-keepclassmembers class * implements android.os.Parcelable { 
    static ** CREATOR; 
} 

-keepclassmembers class **.R$* { 
    public static <fields>; 
} 

-keepclassmembers class * { 
    @android.webkit.JavascriptInterface <methods>; 
} 

最重要的是,我們要保留那些可能被AndroidManifest.xml引用的基礎類。如果你的manifest包含其他類和方法,你也必須這樣指定。

我們保留註解,因爲他們可能被客製化的remoteview使用。

我們保留任何客製化的View的擴展和其他擁有典型的構造函數的類,因爲他們可能被XML佈局文件引用。

我們保留在自定義的Context 擴展中onClick處理方法,因爲他們可能被xml佈局文件引用。

我們也保留那些Parcelable 實現類重點被要求的靜態域,以爲他們可能被introspection訪問

我們保留自動生成的R類的被引用的內部類的靜態域,以防萬一你的代碼被introspection訪問.要注意的是,編譯器已經內聯了原始類型的域,所以Proguard可以完全移除這些類,因爲這些類不會被引用所以也不會被需求。

最後,我們保留註解的javascript藉口方法,這樣他們可以通過他們的原始名字被訪問。那些被有被註解的JavaScript方法(target api小於4。2)也需要被手動註解。

如果你使用另加的Google Api,你就需要指定那些,舉個例子:

-libraryjars /usr/local/android-sdk/add-ons/google_apis-7_r01/libs/maps.jar

如果你正在使用可選的GoogleIf License Verification Library,你可以將它的code和你的code一起混淆,爲了能讓庫正常工作,你必須保留它的ILicensingService 接口:

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

如果你正在使用Android的兼容包,你應該添加以下命令行,讓ProGuard知道,庫引用一些類,可能不是在所有版本的api中都可用。

-dontwarn android.support.** 

未完待續…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章