編輯:關於Android編程
手動添加的配置,一般以”-keep”開頭,常用的配置命令分別示例如下:
假設android工程中有一個接口和一個類:
package com.ticktick.example; public interface TestInterface { public void test(); } public class Test { private String mTestString; private final int mMinValue; private final int mMaxValue; public Test( int min, int max){ mMinValue = min; mMaxValue = max; } public int getMinValue() { return mMinValue; } public int getMaxValue() { return mMaxValue; } public void setTestString(String testStr ) { mTestString = testStr; } }
1.不混淆某個類的構造函數
例如不混淆Test類的構造函數
-keepcalssmembers clsss com.ticktick.example.Text{ public(int,int) }
2.不混淆某個包下所有的類或者指定的類
例如不混淆package com.ticktick.example下的所有的類/接口
#不混淆這個包下的所有的類 -keep class com.ticktick.example.**{*;}
例如不混淆com.ticktick.example.Text類
-keep class com.ticktick.example.Text{*;}
如果希望不混淆某個接口,則把上述命令的class替換為interface即可.
3.不混淆某個類的特定的函數
例如不混淆com.ticktick.example.Test類中的setTestString函數
-keepclassmembers class com.ticktick.example.Test{ public void setTestString(java.lang.String); }
4.不混淆某個類的子類,某個接口的實現
例如不混淆com.ticktick.example.Test的子類
-keep public class * extend com.ticktick.example.Test
例如不混淆com.ticktick.example.TestInterface的實現
-keep class * implements com.ticktick.example.TestInterface{ public static final com.ticktick.example.TestInterface$Creator *; }
5.注意第三方依賴包
例如添加android-support-v4.jar依賴包
-libraryjars libs/android-support-v4.jar -dontwarn android.support.v4.**{*;} -keep class android.support.v4.**{*;} -keep interface android.support.v4.**{*;}
注意添加dontwarn,因為默認情況下proguard會檢查每一個引用是否正確,但是第三方庫裡往往有些不會用到的類,沒有正確引用,所有如果不配置的話,系統會報錯.
枯澀的語法總是避免不了的.上面的小例子對簡單的配置進行了一下描述,下面是詳細的語法.
#例如對一個可執行jar包來說,需要保護main的入口類,對一個類庫來說需要保護它的所有public元素 -keep public class MyMain{ public static void main(java.lang.String[]); }-keepclassmembers {Modifier}{class_specification}
#例如指定繼承了Serizalizable的類的如下成員不被混淆,成員屬性和方法,非私有的屬性非私有的方法. -keepclassmembers class * implements java.io.Serializable{ static final long seriaVersionUID; !private-keepclasseswithmembers{Modifier}{class_specification}保護指定成員的類,根據成員確定一些將要被保護的類; !private ; private void writeObject(java.io.ObjectOuputStream); }
就是說如果一個類含有以下的成員,那麼這個類會被保護
#保護含有main方法的類以及這個類的main方法 -keepclasseswithmembers public class * { public static void main(java.lang.String[]); }-keepnames {Modifier}{class_specification} 這個是-keep,allowshrinking {Modifier}{class_specification}的簡寫.意思是說允許壓縮操作,如果在壓縮過程中沒有被刪除,那麼類名和該類中的成員的名字會被保護 -keepclassmembernames {Modifier}{class_specification}如果在壓縮過程中沒有被刪除在保護這個類中的成員
-keepclasseswithmembers {Modifier}{class_specification}如果在壓縮過程中該類沒有被刪除,同樣如果該類中有某個成員字段或者方法,那麼保護這個類和這個方法.
-printseeds{filename}將keep的成員輸出到文件或者打印到標准輸出流.
#查找字典文件的格式:一行一個單詞,空行忽略,重復忽略 # 這裡巧妙地使用java中的關鍵字作字典,混淆之後的代碼更加不利於閱讀 # # This obfuscation dictionary contains reserved Java keywords. They can't # be used in Java source files, but they can be used in compiled class files. # Note that this hardly improves the obfuscation. Decent decompilers can # automatically replace reserved keywords, and the effect can fairly simply be # undone by obfuscating again with simpler names. # Usage: # java -jar proguard.jar ..... -obfuscationdictionary keywords.txt # do if for int new try byte case char else goto long this void break catch class const final float short super throw while double import native public return static switch throws boolean default extends finally package private abstract continue strictfp volatile interface protected transient implements instanceof synchronized-classobfuscationdictionary {filename}指定一個混淆類名的字典,字典格式與-obfuscationdictionary相同 -packageobfuscationdictionary {filename}指定一個混淆包名的字段 -oberloadaggressively 混淆的時候大量使用重載,多個方法名使用同一個混淆名,但是它們的方法簽名不同,這可以使包的體積減小一部分也可以加大理解難度.
不過這個配置有一定的限制
Sun的JDK1.2上會報異常 Sun JRE 1.4上重載一些方法之後會導致序列化失敗 Sun JRE 1.5上pack200 tool重載一些類之後會報錯 java.lang.reflect.Proxy類不能處理重載的方法-useuniqueclassmembernames 指定相同的混淆名對應相同的方法名,不同的混淆名對應不同的方法名.如果不設置這個選項,同一個類中將會有很多方法映射到相同的方法名.這項配置會稍微增加輸出文件中的代碼,但是它能夠保證 保存下來的mapping文件能夠在隨後的增量混淆中繼續被遵守,避免重新命名.比如說兩個接口擁有同名的方法和相同的簽名,如果沒有這個配置,在第一次打包混淆之後它們兩個方法可能會被賦予不同的混淆名.如果下一次添加代碼有一個類同時實現了這兩個接口,那麼混淆的時候必然會將兩個混淆後的方法名統一起來.這樣就必須要改混淆文件其中一處的配置,也就不能保證前後兩次混淆的mapping文件一致了(如果想用一份mappping文件迭代更新的話,這項配置比較有用). -dontusemixedcaseclassnames 指定在混淆的時候不使用大小寫混用的類名.默認情況下混淆後的類名可能同時包含大寫字母和小寫字母.這樣的jar並沒有什麼問題,只有在大小寫不敏感的window系統上解壓時,才會涉及問題.因為大小寫不區分,可能會導致部分文件在解壓的時候相互覆蓋. -keeppackagenames{package_filter} 聲明不混淆指定的包名,配置的過濾器是逗號隔開的一組包名.包名可以包含? *通配符,並且可以在前面加!否定符 -flatternpackagenames{packagename} 所有重命名的包都重新打包,並把所有的類移動到packagename包下面.如果沒有指定packagename或者packagename為”“,那麼所有的類都會被移動到根目錄下. -repackageclasses{package_name} 所有重新命名類都重新打包,並把它們移動到指定的packagename目錄下.這項配置會覆蓋-flatternpackagehierarchy的配置.他可以使代碼體積更小,並且更加難以理解.
需要注意的是如果需要從目錄中讀取資源文件,移動包的位置可能會導致異常.如果出現這個問題,就不要用這個配置了.
-keepattributes{attribute_filter} 指定受保護的屬性.可以有一個或者多個該配置項,每個配置後面跟隨的是java虛擬機和proguard支持的attribute(具體支持的屬性先看這裡),兩個屬性之間用逗號分隔.屬性名可以使用通配符,或者! 將某個屬性排除在外.當混淆一個類庫的時候至少要保持InnerClasses,Exceptions,Signature屬性.為了跟蹤異常信息,需要把SourceFile,LineNumberTable兩個屬性保留.如果代碼中有用到注解,需要Annotion屬性.#可以分開寫 -keepattributes SourceFile, LineNumberTable -keepattributes *Annotation* -keepattributes EnclosingMethod # 可以直接寫在一行 -keepattributes Exceptions, InnerClasses, Signature, Deprecated, SourceFile, LineNumberTable, *Annotation*, EnclosingMethod-keepparameternames 指定被保護的方法的參數類型和參數名不被混淆.這項配置在混淆一些類庫的時候特別有用,因為根據IDE提示的參數名和參數類型,開發者可以根據語意獲得一些信息. -adaptclassstrings{classfilter}指定字符串常量如果與類名相同,也需要被混淆.如果沒有加classfilter,所有的符合要求的字符串常量都會被混淆;如果帶classfilter,只有在匹配的類中的字符串常量才會受此影響.例如在你的代碼中有大量的類名對應的字符串的hard-code,並且不想保留它們的本名,那就可以利用哦這項配置來完成. -adaptresourcefileanmes{file_filter} 如果資源文件與某類同名,那麼混淆後資源文件被命名為與之對應的類的混淆名.不加file_filter的情況下,所有資源文件都受此影響,加了file_filter的情況只有匹配的類才受此類的影響. -adaptresourcefilecontents{file_filter}指定資源文件的中的類名隨混淆後的名字更新.根據被混淆的名字的前後映射關系,更新文件中對應的包名和類名.
? 匹配單個字符 * 匹配類名中的任何部分,但不包含額外的包名 ** 匹配類名中的任何部分,並且可以包含額外的包名 % 匹配任何基礎類型的類型名 ... 匹配認識數量 任意類型的參數匹配任何構造器 匹配任何字段名 *(當用在類內部時) 匹配任何字段和方法 $ 指內部類
C++ LooperLooperLooper類[system/core/libutils/Looper.cpp]提供了pollOnce(),wake()函數來完成睡眠等待
1.引言 所謂的消息推送就是從服務器端向移動終端發送連接,傳輸一定的信息。比如一些新聞客戶端,每隔一段時間收到一條或者多條通知,這就是從服務器端傳來的推送消息;還
原因一:Activity的啟動模式那麼Activity以哪種啟動模式進行跳轉時,會導致目標Activity獲取不到傳遞過來的數據呢?在上一篇博客中講到Activity以不
1、為什麼需要異步加載。因為我們都知道在Android中的是單線程模型,不允許其他的子線程來更新UI,只允許UI線程(主線程更新UI),否則會多個線程都去更新UI會造成U