介紹
之前介紹瞭如何使用命令行將Jar包根據配置文件進行ProGuard,以及ProGuard的過程,會遇到的問題等。接下來會介紹常用的ProGuard如何配置參數。不常用的可以在官網中查詢如何使用。
java -jar proguard.jar @myconfig.pro
Filter
每一個類、屬性、方法都會有一個全名,例如java.lang.String
。而我們也可以通過正則表達式來過濾我們所需要的名稱。
-
?
:在class中匹配任意的單個字符 例如:mypackage.Test?
可以匹配mypackage.Test1
,mypackage.Test2
,但是不能匹配mypackage.Test12
-
*
:匹配任意class名稱中的一部分 例如:mypackage.*Test*
可以匹配mypackage.Test
,也可以匹配mypackage.YouTestApplication
,但是不能匹配mypackage.subpackage.MyTest
-
**
:可以匹配class名稱中的任意一部分,可以包括任何數字或者包分隔符。 例如:**.Test
可以匹配除了根目錄下所有包名下的Test類。mypackage.**
則可以匹配所有在mypackage
和它子目錄的所有類
而Fields和Methods與Java中類似。除了Method的參數中不需要包含它的名字,就和Javap中一樣。而匹配規則如下:
-
<init>
:匹配任意構造函數 -<fields>
:匹配任意屬性 -<methods>
:匹配任意函數 -*
:匹配任意屬性或者函數
Input / Output Options
- @filename
這種方式,是
-include filename
的縮寫,該選項的作用是遞歸讀取所給文件中的屬性 - -basedirectory directoryPath 指定配置文件的目錄
- -injars class_path 指定輸入Jar包的路徑,可以指定多個路徑,而輸入的Entity可以被過濾
- -outjars class_path 指定輸出Jar包路徑,同上而輸出的Entity可以被過濾
- libraryjars class_path
指定要被處理的Jar包。這些文件不會被打包到output jar包中。指定的Library應該至少包含一個Class文件被Application Class文件中使用
extended
繼承了。 - -skipnonpubliclibraryclasses 當讀取library的時候,跳過non-public的類,以提升處理速度並且減少ProGuard內存佔用。默認ProGuard會讀取public以及non-public的類。然而,non-public的類通常沒有關聯的。可以忽略他們,提升ProGuard速度,而且也不會影響output。但是有一些lib,例如JSE run-time,包含了non-public的類,但是它還可以被public的library繼承。所以你不能使用這個option。如果因爲這個option無法找到那個class的話 ,ProGuard會打印出來Warning的。
- -dontskipnonpubliclibraryclasses 從4.5版本開始,默認就指定了該屬性。該屬性制定了不要忽略non-public的類
- -dontskipnonpubliclibraryclassmembers 指定不要忽略package visible的類成員(Field以及Method)。默認的,ProGuard在解析classes會跳過這些類成員,因爲程序通常不會引用它們。有些情況下,程序的包和Library的包相同,從而可以引用包可見的類成員。在這種情況下,實際讀取類成員是有用的,以確保處理後的代碼保持一致。
- keepdirectories directory_filter
指定輸出路徑中需要Keep的目錄。默認情況下,目錄的Entries會被移除掉,用來減少Jar包的大小。但是有可能程序會有
MyClass.class.getResource("")
這種代碼出現,如果沒有指定一個Directory Filter的話,那麼所有的目錄都會被Keep住。如果有Filter的話,則會Keep匹配目錄。
Keep Options
- -keep: Keep住所有繼承自Activity、Application的類
-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住所有繼承自View類中的public構造函數以及所有以public void set
開始的函數。
-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*(...); }
- -keepclassmembers Keep住類中的成員。
-keepclassmembers class * implements java.io.Serializable { private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); } -keepclassmembers class * implements android.os.Parcelable { static android.os.Parcelable$Creator CREATOR; } -keepclassmembers class **.R$* { public static <fields>; }
- -keepclasseswithmembers Keep住能匹配到規則的類。如下,會Keep住所有構造函數帶有Context、AttributeSet的類。
-keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); }
- -keepclassmembernames Keep住類成員。如果它們沒有在Shrink階段被移除的話
-keepclassmembernames class scala.concurrent.forkjoin.ForkJoinPool { long eventCount; int workerCounts; int runControl; scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode syncStack; scala.concurrent.forkjoin.ForkJoinPool$WaitQueueNode spareStack; }
- -keepclasseswithmembernames 根據類成員名稱來Keep住類。如下,如果有Native函數的類全部都會被Keep住
-keepclasseswithmembernames class * { native <methods>; }