Android混淆

代碼混淆(Obfuscated code)亦稱花指令府框,是將計算機程序的代碼主经,轉(zhuǎn)換成一種功能上等價偏竟,但是難于閱讀和理解的形式的行為硬纤。(混淆就是對發(fā)布出去的程序進行重新組織和處理,使得處理后的代碼與處理前代碼完成相同的功能咱士,而混淆后的代碼很難被反編譯立由,即使反編譯成功也很難得出程序的真正語義)

為什么要加代碼混淆?
1.保護代碼
2.精簡編譯后程序大小(混淆器將代碼中的所有變量、函數(shù)序厉、類的名稱變?yōu)楹喍痰挠⑽淖帜复?

開啟混淆
通常我們需要找到項目路徑下app目錄下的build.gradle文件
找到minifyEnabled這個配置,然后設置為true即可.

proguard-rules.pro里面定義了我們的混淆規(guī)則

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
Proguard關鍵字
關鍵字                        描述
  -dontwarn                    dontwarn是一個和keep可以說是形影不離,尤其是處理引入的library時.
  -keep                        保留類和類中的成員锐膜,防止被混淆或移除
  -keepnames                   保留類和類中的成員,防止被混淆弛房,成員沒有被引用會被移除
  -keepclassmembers            只保留類中的成員道盏,防止被混淆或移除
  -keepclassmembernames        只保留類中的成員,防止被混淆文捶,成員沒有引用會被移除
  -keepclasseswithmembers      保留類和類中的成員荷逞,防止被混淆或移除,保留指明的成員
  -keepclasseswithmembernames  保留類和類中的成員粹排,防止被混淆种远,保留指明的成員,成員沒有引用會被移除
  -keepattributes  保留某些屬性不被混淆顽耳,可選(*Annotation*,InnerClasses坠敷,Signature,SourceFile,LineNumberTable)
  -keep

Proguard通配符
通配符       描述
  <field>     匹配類中的所有字段
  <method>    匹配類中所有的方法
  <init>      匹配類中所有的構造函數(shù)
  *           匹配任意長度字符斧抱,不包含包名分隔符(.)
  **          匹配任意長度字符常拓,包含包名分隔符(.)
  ***         匹配任意參數(shù)類型

引入的library可能存在一些無法找到的引用和其他問題,在build時可能會發(fā)出警告,如果我們不進行處理,通常會導致build中止.因此為了保證build繼續(xù),我們需要使用dontwarn處理這些我們無法解決的library的警告

-dontwarn com.mob.**

引入的library保留其包下面的類以及子包

-keep class com.mob.**{*;}

通常引入的library渐溶,如下配置

-keep class com.mob.**{*;}
-dontwarn com.mob.**
哪些不應該混淆
  • 使用了自定義控件那么要保證它們不參與混淆
  • 使用了枚舉要保證枚舉不被混淆
  • 對第三方庫中的類不進行混淆
  • 運用了反射的類也不進行混淆
  • 使用了 Gson 之類的工具要使 JavaBean 類即實體類不被混淆
  • 在引用第三方庫的時候辉浦,一般會標明庫的混淆規(guī)則的,建議在使用的時候就把混淆規(guī)則添加上去茎辐,免得到最后才去找
  • 有用到 WebView 的 JS 調(diào)用也需要保證寫的接口方法不混淆宪郊,原因和第一條一樣
  • Parcelable 的子類和 Creator 靜態(tài)成員變量不混淆掂恕,否則會產(chǎn)生Android.os.BadParcelableException 異常
  • 使用的四大組件,自定義的Application* 實體類
  • JNI中調(diào)用的類
  • Layout布局使用的View構造函數(shù)(自定義控件)弛槐、android:onClick等懊亡。
模板
#############################################
#
# -基本不用動區(qū)域
#
#############################################


# 指定代碼的壓縮級別 0 - 7(指定代碼進行迭代優(yōu)化的次數(shù),在Android里面默認是5乎串,這條指令也只有在可以優(yōu)化時起作用店枣。)
-optimizationpasses 5
# 混淆時不會產(chǎn)生形形色色的類名(混淆時不使用大小寫混合類名)
-dontusemixedcaseclassnames
# 指定不去忽略非公共的庫類(不跳過library中的非public的類)
-dontskipnonpubliclibraryclasses
# 指定不去忽略包可見的庫類的成員
-dontskipnonpubliclibraryclassmembers
#不進行優(yōu)化,建議使用此選項叹誉,
-dontoptimize
# 不進行預校驗,Android不需要,可加快混淆速度鸯两。
-dontpreverify
# 屏蔽警告(忽略警告,否則打包可能會不成功)
-ignorewarnings
# 指定混淆是采用的算法长豁,后面的參數(shù)是一個過濾器
# 這個過濾器是谷歌推薦的算法钧唐,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# 保護代碼中的Annotation不被混淆
-keepattributes *Annotation*
# 避免混淆泛型, 這在JSON實體映射時非常重要
-keepattributes Signature
# 拋出異常時保留代碼行號
-keepattributes SourceFile,LineNumberTable
# 保留sdk系統(tǒng)自帶的一些內(nèi)容
-keepattributes Exceptions,InnerClasses,Deprecated,EnclosingMethod
#優(yōu)化時允許訪問并修改有修飾符的類和類的成員,這可以提高優(yōu)化步驟的結果匠襟。
# 比如钝侠,當內(nèi)聯(lián)一個公共的getter方法時,這也可能需要外地公共訪問酸舍。
# 雖然java二進制規(guī)范不需要這個帅韧,要不然有的虛擬機處理這些代碼會有問題。當有優(yōu)化和使用-repackageclasses時才適用父腕。
#指示語:不能用這個指令處理庫中的代碼弱匪,因為有的類和類成員沒有設計成public ,而在api中可能變成public
-allowaccessmodification
#當有優(yōu)化和使用-repackageclasses時才適用。
-repackageclasses ''
 # 混淆時記錄日志(打印混淆的詳細信息)
 # 這句話能夠使我們的項目混淆后產(chǎn)生映射文件
 # 包含有類名->混淆后類名的映射關系
-verbose

#############################################
#
# -默認保留
#
#############################################

# 保持哪些類不被混淆
#繼承activity,application,service,broadcastReceiver,contentprovider....不進行混淆
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.support.multidex.MultiDexApplication
-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 * extends android.view.View
-keep class android.support.** {*;}## 保留support下的所有類及其內(nèi)部類

-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
#表示不混淆上面聲明的類璧亮,最后這兩個類我們基本也用不上萧诫,是接入Google原生的一些服務時使用的。
#----------------------------------------------------

# 保留繼承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**


#表示不混淆任何包含native方法的類的類名以及native方法名枝嘶,這個和我們剛才驗證的結果是一致
-keepclasseswithmembernames class * {
    native <methods>;
}


#這個主要是在layout 中寫的onclick方法android:onclick="onClick"帘饶,不進行混淆
#表示不混淆Activity中參數(shù)是View的方法只估,因為有這樣一種用法干签,在XML中配置android:onClick=”buttonClick”屬性,
#當用戶點擊該按鈕時就會調(diào)用Activity中的buttonClick(View view)方法卿樱,如果這個方法被混淆的話就找不到了
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}

#表示不混淆枚舉中的values()和valueOf()方法竞阐,枚舉我用的非常少缴饭,這個就不評論了
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#表示不混淆任何一個View中的setXxx()和getXxx()方法,
#因為屬性動畫需要有相應的setter和getter的方法實現(xiàn)骆莹,混淆了就無法工作了颗搂。
-keep public class * extends android.view.View{
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

#表示不混淆Parcelable實現(xiàn)類中的CREATOR字段,
#毫無疑問幕垦,CREATOR字段是絕對不能改變的丢氢,包括大小寫都不能變傅联,不然整個Parcelable工作機制都會失敗。
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
# 這指定了繼承Serizalizable的類的如下成員不被移除混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    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();
}
# 保留R下面的資源
#-keep class **.R$* {
# *;
#}
#不混淆資源類下static的
-keepclassmembers class **.R$* {
    public static <fields>;
}

# 對于帶有回調(diào)函數(shù)的onXXEvent疚察、**On*Listener的蒸走,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
    void *(**On*Listener);
}

# 保留我們自定義控件(繼承自View)不被混淆
-keep public class * extends android.view.View{
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

#
#----------------------------- WebView(項目中沒有可以忽略) -----------------------------
#
#webView需要進行特殊處理
-keepclassmembers class fqcn.of.javascript.interface.for.Webview {
   public *;
}
-keepclassmembers class * extends android.webkit.WebViewClient {
    public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
    public boolean *(android.webkit.WebView, java.lang.String);
}
-keepclassmembers class * extends android.webkit.WebViewClient {
    public void *(android.webkit.WebView, jav.lang.String);
}
#在app中與HTML5的JavaScript的交互進行特殊處理
#我們需要確保這些js要調(diào)用的原生方法不能夠被混淆,于是我們需要做如下處理:
-keepclassmembers class com.ljd.example.JSInterface {
    <methods>;
}

#
# ----------------------------- 其他的 -----------------------------
#
# 刪除代碼中Log相關的代碼
-assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int i(...);
    public static int w(...);
    public static int d(...);
    public static int e(...);
}

# 保持測試相關的代碼
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**


# 記錄生成的日志數(shù)據(jù),gradle build時在本項根目錄輸出
# apk 包內(nèi)所有 class 的內(nèi)部結構
-dump proguard/class_files.txt
# 未混淆的類和成員
-printseeds proguard/seeds.txt
# 列出從 apk 中刪除的代碼
-printusage proguard/unused.txt
# 混淆前后的映射
-printmapping proguard/mapping.txt



#############################################
#
# -實體類 以及 Gson
# --------(實體Model不能混淆貌嫡,否則找不到對應的屬性獲取不到值)-----
#
#############################################

-dontwarn org.jbase.yxt.yyd.pyw.response.**
#對含有反射類的處理(gson反射解析)
-keep class org.jbase.yxt.yyd.pyw.response.** {*;}

-dontwarn com.google.gson.**
-keep class com.google.gson.**{*;}
-keep interface com.google.gson.**{*;}
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末比驻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子岛抄,更是在濱河造成了極大的恐慌嫁艇,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弦撩,死亡現(xiàn)場離奇詭異步咪,居然都是意外死亡,警方通過查閱死者的電腦和手機益楼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門猾漫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人感凤,你說我怎么就攤上這事悯周。” “怎么了陪竿?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵禽翼,是天一觀的道長。 經(jīng)常有香客問我族跛,道長闰挡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任礁哄,我火速辦了婚禮长酗,結果婚禮上,老公的妹妹穿的比我還像新娘桐绒。我一直安慰自己夺脾,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布茉继。 她就那樣靜靜地躺著咧叭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烁竭。 梳的紋絲不亂的頭發(fā)上菲茬,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音,去河邊找鬼生均。 笑死,一個胖子當著我的面吹牛腥刹,可吹牛的內(nèi)容都是我干的马胧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼衔峰,長吁一口氣:“原來是場噩夢啊……” “哼佩脊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起垫卤,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤威彰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后穴肘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歇盼,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年评抚,在試婚紗的時候發(fā)現(xiàn)自己被綠了豹缀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡慨代,死狀恐怖邢笙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侍匙,我是刑警寧澤氮惯,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站想暗,受9級特大地震影響妇汗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜说莫,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一铛纬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧唬滑,春花似錦告唆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稻艰,卻和暖如春懂牧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工僧凤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留畜侦,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓躯保,卻偏偏與公主長得像旋膳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子途事,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容