Gradle For Android(四)Gradle編譯中神秘的混淆

Gradle For Android(二) 多渠道打包與簽名配置中說過在日常開發(fā)中進(jìn)行打包apk的一些往事,打包測(cè)試、打包上傳應(yīng)用商店摔认,這些都避免不了喧兄。當(dāng)然在這過程中无畔,除了簽名打包,當(dāng)然少不了代碼的混淆了吠冤。代碼混淆浑彰,說白了就是代碼壓縮、代碼混淆以及資源壓縮的優(yōu)化拯辙。依靠 ProGuard郭变,將所有類名、方法名重命名為無意義的簡(jiǎn)單名稱涯保,增加了逆向工程難度诉濒。依靠Gradle插件,移除了沒有使用的資源夕春,減少了apk大小 未荒。

Gradle For Android 導(dǎo)讀

正文:

一、Android Gradle 混淆中的配置

一般及志,在我們的application moudle中的gradle配置項(xiàng)buildTypes中,例如如下:

  release { //release類型
            minifyEnabled false
            // 啟用混淆
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

這里minifyEnabled表示啟動(dòng)混淆片排,一般啟動(dòng)混淆編譯速度會(huì)比較慢,因此在編譯debug版本的時(shí)候一般默認(rèn)不開啟速侈。proguard-rules.pro這個(gè)表示該module默認(rèn)的混淆文件率寡,我們可以直接將混淆內(nèi)容寫在這里。另外倚搬,這里也要說下**shrinkResources **這個(gè)字段冶共,當(dāng)為true的時(shí)候,表示打開資源壓縮潭枣,編譯時(shí)會(huì)去掉沒被使用的資源文件比默。

修改后的配置代碼如下:

  buildTypes {//表示構(gòu)建類型 一般有release debug 兩種

        debug{
            buildConfigField 'String','STATE_TEST','"debug"'//buildConfigField
            resValue "string", "test_value", "AGradle_debug"http://resValue
        }

        release { //release類型
            minifyEnabled true  // 啟用混淆
            shrinkResources true  // 資源壓縮
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            buildConfigField 'String','STATE_TEST','"release"' //buildConfigField
            resValue "string", "test_value", "AGradle_release" //resValue
        }

    }

二、混淆規(guī)則舉例

這里貼下網(wǎng)上認(rèn)為比較"通用"的混淆規(guī)則如下:

#指定壓縮級(jí)別
-optimizationpasses 5

#不跳過非公共的庫的類成員
-dontskipnonpubliclibraryclassmembers

#混淆時(shí)采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#把混淆類中的方法名也混淆了
-useuniqueclassmembernames

#優(yōu)化時(shí)允許訪問并修改有修飾符的類和類的成員 
-allowaccessmodification

#將文件來源重命名為“SourceFile”字符串
-renamesourcefileattribute SourceFile
#保留行號(hào)
-keepattributes SourceFile,LineNumberTable

#保持所有實(shí)現(xiàn) Serializable 接口的類成員
-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();
}

#Fragment不需要在AndroidManifest.xml中注冊(cè)盆犁,需要額外保護(hù)下
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment

# 保持測(cè)試相關(guān)的代碼
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**

"通用"命咐,當(dāng)然真正實(shí)現(xiàn)通用,除了上面的混淆規(guī)則谐岁,需要根據(jù)項(xiàng)目需要添加自定義的混淆規(guī)則

例如:

  • 第三方庫混淆規(guī)則醋奠。這個(gè)比較常見榛臼,直接接入官方說明文檔。

  • model實(shí)體類窜司,典型在轉(zhuǎn)化json的時(shí)候沛善,必須保證model不被混淆,因此需加入--keep public class

JNI中調(diào)用的類以及方法不可被混淆

  • WebView中JavaScript調(diào)用的接口不混淆

  • AndroidMainfest塞祈、四大組件以及Application的子類不混淆

  • Parcelable的子類和Creator靜態(tài)成員變量不混淆金刁,否則會(huì)產(chǎn)生Android.os.BadParcelableException異常

  • Layout布局使用的View構(gòu)造函數(shù)、android:onClick等议薪。

三尤蛮、混淆結(jié)果的檢測(cè)

在開啟混淆后,通過混淆配置打包后斯议,會(huì)在目錄:

<module>/outputs/mapping/<渠道名>/<編譯類型>/..

如圖所示:

gradle.png

下面大概說明下:

  • dump.txt :描述APK文件中所有類的內(nèi)部結(jié)構(gòu)
  • mapping.txt :提供混淆前后類产捞、方法、類成員等的對(duì)照表
  • seeds.txt:列出沒有被混淆的類和成員

usage.txt: 列出被移除的代碼

我們可以根據(jù) seeds.txt 文件檢查未被混淆的類和成員中是否已包含所有期望保留的哼御,再根據(jù) usage.txt 文件查看是否有被誤移除的代碼坯临。建議讀者都試下去查看下,必須有收獲~

四恋昼、自定義混淆規(guī)則

(一) proguard 參數(shù)
  • include {filename} 從給定的文件中讀取配置參數(shù)

  • basedirectory {directoryname} 指定基礎(chǔ)目錄為以后相對(duì)的檔案名稱

  • injars {class_path} 指定要處理的應(yīng)用程序jar,war,ear和目錄

  • outjars {class_path} 指定處理完后要輸出的jar,war,ear和目錄的名稱

  • libraryjars {classpath} 指定要處理的應(yīng)用程序jar,war,ear和目錄所需要的程序庫文件

  • dontskipnonpubliclibraryclasses 指定不去忽略非公共的庫類看靠。

  • dontskipnonpubliclibraryclassmembers 不跳過非公共的庫的類成員

上面部分參數(shù),日常移動(dòng)開發(fā)的應(yīng)用混淆中也不是經(jīng)常使用到的焰雕,如果讀者想進(jìn)一步深入了解每個(gè)參數(shù)實(shí)際作用衷笋,可以去官網(wǎng)進(jìn)行查閱,這里筆者不做太多說明哈矩屁。

(二)keep 參數(shù)
  • keep {Modifier(屬性辟宗,例如public,以下說明一致)} {class_specification(具體類或者成員的位置吝秕,以下說明一致)} 防止類和成員被移除或者被重命名

  • keepclassmembers {modifier} {class_specification} 防止成員被移除或者被重命名

  • keepnames {class_specification} 防止成員被重命名)

  • keepclassmembernames {class_specification} 防止擁有該成員的類和成員被移除或者被重命名

  • keepclasseswithmembernames {class_specification} 防止擁有該成員的類和成員被重命名

(三)混淆的必須知道的一些規(guī)則

1泊脐、一般規(guī)則形式:

[命令] [類] {
    [成員] 
}

:代表相關(guān)指定條件的類,例如

  • 具體的類
  • 訪問修飾符(public烁峭、protected容客、private
  • 通配符*,匹配任意長(zhǎng)度字符约郁,但不含包名分隔符(.)
  • 通配符**缩挑,匹配任意長(zhǎng)度字符,并且包含包名分隔符(.)
  • extends鬓梅,即可以指定類的基類
  • implement供置,匹配實(shí)現(xiàn)了某接口的類
  • $,內(nèi)部類

成員:代表指定類后符合指定條件的成員變量绽快,例如

  • 匹配所有構(gòu)造器
  • 匹配所有域
  • 匹配所有方法
  • 通配符*芥丧,匹配任意長(zhǎng)度字符紧阔,但不含包名分隔符(.)
  • 通配符**,匹配任意長(zhǎng)度字符续担,并且包含包名分隔符(.)
  • 通配符***擅耽,匹配任意參數(shù)類型
  • ,匹配任意長(zhǎng)度的任意類型參數(shù)物遇。比如void test(…)就能匹配任意 void test(String a) 或者是 void test(int a, String b) 這些方法乖仇。
  • 訪問修飾符(publicprotected询兴、private

舉個(gè)例子这敬,假如需要將name.huihui.test包下所有繼承Activitypublic類及其構(gòu)造函數(shù)都保持住,可以這樣寫:

-keep public class name.huihui.test.** extends Android.app.Activity {
    <init>
}

2蕉朵、常用自定義混淆規(guī)則

  • 不混淆某個(gè)類
-keep public class name.huihui.example.Test { *; }
  • 不混淆某個(gè)包所有的類
-keep class name.huihui.test.** { *; }
  • 不混淆某個(gè)類的子類
-keep public class * extends name.huihui.example.Test { *; }
  • 不混淆所有類名中包含了“model”的類及其成員
-keep public class **.*model*.** {*;}
  • 不混淆某個(gè)接口的實(shí)現(xiàn)
-keep class * implements name.huihui.example.TestInterface { *; }
  • 不混淆某個(gè)類的構(gòu)造方法
-keepclassmembers class name.huihui.example.Test { 
  public <init>(); 
}
  • 不混淆某個(gè)類的特定的方法
-keepclassmembers class name.huihui.example.Test { 
  public void test(java.lang.String); 
}

五、自定義資源保持規(guī)則

前面說的通過shrinkResources true開啟資源壓縮后阳掐,未被使用的資源默認(rèn)不會(huì)被打包進(jìn)去始衅。如果開發(fā)者是自定義保留指定的資源文件,可以在res/raw/ 路徑下創(chuàng)建一個(gè) xml 文件缭保,例如 keep.xml汛闸,進(jìn)行自定義混淆規(guī)則。

一般屬性有:

  • tools:keep 定義哪些資源需要被保留(資源之間用“,”隔開)
  • tools:discard 定義哪些資源需要被移除(資源之間用“,”隔開)
  • tools:shrinkMode 開啟嚴(yán)格模式

例如:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
    tools:discard="@layout/unused2"
    tools:shrinkMode="strict"/>

最后感謝@ 光源coder提供的混淆手冊(cè)艺骂,總結(jié)的不錯(cuò)~

希望對(duì)有些開發(fā)者有幫助具體查看可以github上的demo诸老,也歡迎加入開發(fā)交流群哈,詳情看個(gè)人簡(jiǎn)介钳恕。下一篇是對(duì)gradle的混淆說明别伏,歡迎讀者閱讀

DEMO

Gradle For Android(四)Gradle編譯中神秘的混淆

傻小孩b mark共勉,寫給在成長(zhǎng)路上奮斗的你

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末忧额,一起剝皮案震驚了整個(gè)濱河市厘肮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌睦番,老刑警劉巖类茂,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異托嚣,居然都是意外死亡巩检,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門示启,熙熙樓的掌柜王于貴愁眉苦臉地迎上來兢哭,“玉大人,你說我怎么就攤上這事丑搔∠闷埃” “怎么了提揍?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)煮仇。 經(jīng)常有香客問我劳跃,道長(zhǎng),這世上最難降的妖魔是什么浙垫? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任刨仑,我火速辦了婚禮,結(jié)果婚禮上夹姥,老公的妹妹穿的比我還像新娘杉武。我一直安慰自己,他們只是感情好辙售,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布轻抱。 她就那樣靜靜地躺著,像睡著了一般旦部。 火紅的嫁衣襯著肌膚如雪祈搜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天士八,我揣著相機(jī)與錄音容燕,去河邊找鬼。 笑死婚度,一個(gè)胖子當(dāng)著我的面吹牛蘸秘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蝗茁,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼醋虏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了评甜?” 一聲冷哼從身側(cè)響起灰粮,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忍坷,沒想到半個(gè)月后粘舟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佩研,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年柑肴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旬薯。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晰骑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情硕舆,我是刑警寧澤秽荞,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站抚官,受9級(jí)特大地震影響扬跋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凌节,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一钦听、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧倍奢,春花似錦朴上、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至畔裕,卻和暖如春酵镜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背柴钻。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垢粮,地道東北人贴届。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蜡吧,于是被迫代替她去往敵國和親毫蚓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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