代碼混淆

1) 前言

ProGuard是一個(gè)開源的Java代碼混淆器。它可以混淆Android項(xiàng)目里面的java代碼,對(duì)的,你沒(méi)看錯(cuò),僅僅是java代碼。它是無(wú)法混淆Native代碼,資源文件drawable、xml等。

2) ProGuard作用

  • 壓縮: 移除無(wú)效的類、屬性、方法等

  • 優(yōu)化: 優(yōu)化字節(jié)碼,并刪除未使用的結(jié)構(gòu)

  • 混淆: 將類名、屬性名、方法名混淆為難以讀懂的字母,比如a,b,c

3) 混淆注意事項(xiàng)

1. 不能混淆

  • 在AndroidManifest中配置的類,比如四大組件

  • JNI調(diào)用的方法

  • 反射用到的類

  • WebView中JavaScript調(diào)用的方法

  • Layout文件引用到的自定義View

  • 一些引入的第三方庫(kù)(一般都會(huì)有混淆說(shuō)明的)

    這里推薦兩個(gè)開源項(xiàng)目,里面收集了一些第三方庫(kù)的混淆規(guī)則

不難理解,混淆之后,類名會(huì)變成a,b,c這種,通過(guò)包名+類名自然就會(huì)找不到該類了,自然就會(huì)出現(xiàn)ClassNotFoundException異常。這里推薦一篇文章:
http://www.itnose.net/detail/6043297.html

2. Log處理

我們都知道,使用Log的時(shí)候,需要用到TAG,然而TAG我們一般都會(huì)寫成:

private static final String TAG = MainActivity.class.getSimpleName()

這時(shí)候MainActivity如何被混淆的話,log輸出信息就會(huì)變成V/a:xxxxxxx,所以為了讓log輸出信息維持原狀,可以將TAG處理成固定的字符串:

private static final String TAG = "MainActivity"

正好Android Studio里面的Live Templates

[圖片上傳失敗...(image-b36df1-1513066616611)]

能讓你輕輕松松的聲明TAG

[圖片上傳失敗...(image-acf1b7-1513066616610)]

關(guān)于Log處理,推薦一篇文章:https://www.zybuluo.com/shark0017/note/163330

3. Crash信息處理

代碼混淆的時(shí)候記得加上在混淆文件里面記得加上這句:

# keep住源文件以及行號(hào)

-keepattributes SourceFile,LineNumberTable

否則你看到的崩潰信息就會(huì)變成這樣子(圖片來(lái)自bugly)

[圖片上傳失敗...(image-be7db8-1513066616610)]

這里推薦bugly的一篇文章:

http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=26&extra=page%3D1

4)ProGuard使用

1. 常用語(yǔ)法

保留

  • -keep {Modifier} {class_specification} 保護(hù)指定的類文件和類的成員

  • -keepclassmembers {modifier} {class_specification} 保護(hù)指定類的成員,如果此類受到保護(hù)他們會(huì)保護(hù)的更好

  • -keepclasseswithmembers {class_specification} 保護(hù)指定的類和類的成員,但條件是所有指定的類和類成員是要存在。

  • -keepnames {class_specification} 保護(hù)指定的類和類的成員的名稱(如果他們不會(huì)壓縮步驟中刪除)

  • -keepclassmembernames {class_specification} 保護(hù)指定的類的成員的名稱(如果他們不會(huì)壓縮步驟中刪除)

  • -keepclasseswithmembernames {class_specification} 保護(hù)指定的類和類的成員的名稱,如果所有指定的類成員出席(在壓縮步驟之后)

  • -printseeds {filename} 列出類和類的成員-keep選項(xiàng)的清單,標(biāo)準(zhǔn)輸出到給定的文件

壓縮

  • -dontshrink 不壓縮輸入的類文件

  • -printusage {filename}

  • -whyareyoukeeping {class_specification}

優(yōu)化

  • -dontoptimize 不優(yōu)化輸入的類文件

  • -assumenosideeffects {class_specification} 優(yōu)化時(shí)假設(shè)指定的方法,沒(méi)有任何副作用

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

混淆

  • -dontobfuscate 不混淆輸入的類文件

  • -obfuscationdictionary {filename} 使用給定文件中的關(guān)鍵字作為要混淆方法的名稱

  • -overloadaggressively 混淆時(shí)應(yīng)用侵入式重載

  • -useuniqueclassmembernames 確定統(tǒng)一的混淆類的成員名稱來(lái)增加混淆

  • -flattenpackagehierarchy {package_name} 重新包裝所有重命名的包并放在給定的單一包中

  • -repackageclass {package_name} 重新包裝所有重命名的類文件中放在給定的單一包中

  • -dontusemixedcaseclassnames 混淆時(shí)不會(huì)產(chǎn)生形形色色的類名

  • -keepattributes {attribute_name,…} 保護(hù)給定的可選屬性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.

  • -renamesourcefileattribute {string} 設(shè)置源文件中給定的字符串常量

通配符匹配規(guī)則

通配符 規(guī)則
匹配單個(gè)字符
* 匹配類名中的任何部分,但不包含額外的包名
** 匹配類名中的任何部分,并且可以包含額外的包名
% 匹配任何基礎(chǔ)類型的類型名
*** 匹配任意類型名 ,包含基礎(chǔ)類型/非基礎(chǔ)類型
... 匹配任意數(shù)量、任意類型的參數(shù)
<init> 匹配任何構(gòu)造器
<ifield> 匹配任何字段名
<imethod> 匹配任何方法
*(當(dāng)用在類內(nèi)部時(shí)) 匹配任何字段和方法
$ 指內(nèi)部類

更詳細(xì)的語(yǔ)法請(qǐng)戳:http://proguard.sourceforge.net/manual/usage.html#classspecification

2. Android Studio中使用方法

按照上面的語(yǔ)法規(guī)則編寫proguard-rules.pro后,需要在build.gradle中配置,需要混淆的時(shí)候,設(shè)置minifyEnabled為true即可

buildTypes {
    debug {
        minifyEnabled false
    }
    release {
        signingConfig signingConfigs.release
        minifyEnabled true
        proguardFiles 'proguard-rules.pro'
    }
}

3. ProGuard的輸出文件說(shuō)明

混淆后,會(huì)在/build/proguard/目錄下輸出下面的文件

  • dump.txt 描述apk文件中所有類文件間的內(nèi)部結(jié)構(gòu)。

  • mapping.txt 列出了原始的類,方法,和字段名與混淆后代碼之間的映射。

  • seeds.txt 列出了未被混淆的類和成員

  • usage.txt 列出了從apk中刪除的代碼

    當(dāng)我們需要處理crash log的時(shí)候,就可以通過(guò)mapping.txt的映射關(guān)系找到對(duì)應(yīng)的類,方法,字段等。方法如下:

sdk\tools\proguard\bin 目錄下有個(gè)retrace工具可以將混淆后的報(bào)錯(cuò)堆棧解碼成正常的類名
window下為retrace.bat,linux和mac為retrace.sh,

使用方法如下:

  1. 將crash log保存為yourfilename.txt

  2. 拿到版本發(fā)布時(shí)生成的mapping.txt

  3. 執(zhí)行命令retrace.bat -verbose mapping.txt yourfilename.txt

所以我們每次打包版本都需要保存最新的mapping.txt文件。如果要使用到第三方的crash統(tǒng)計(jì)平臺(tái),比如bugly,還需要我們上傳APP版本對(duì)應(yīng)的mapping.txt.每次都要保存最新的mapping文件,那不就很麻煩?放心,gradle會(huì)幫到你,只需要在bulid.gradle加入下面的一句。每次我們編譯的時(shí)候,都會(huì)自動(dòng)幫你保存mapping文件到本地的。

android {
applicationVariants.all { variant ->
        variant.outputs.each { output ->
            if (variant.getBuildType().isMinifyEnabled()) {
                variant.assemble.doLast{
                        copy {
                            from variant.mappingFile
                            into "${projectDir}/mappings"
                            rename { String fileName ->
                                "mapping-${variant.name}.txt"
                            }
                        }
                }
            }
        }
        ......
    }
}

5) 參考

https://blog.gmem.cc/proguard-study-note
http://developer.android.com/intl/zh-cn/tools/help/proguard.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,494評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,714評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,410評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,940評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,776評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,210評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評(píng)論 1 286
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,654評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373

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

  • 混淆代碼能有效防止被反編譯,防止自己的勞動(dòng)成果被別人竊取; ProGuard是一個(gè)開源的Java代碼混淆器。它可以...
    appzy閱讀 2,307評(píng)論 2 18
  • 聲明 這篇文章更多的是做一個(gè)整理,內(nèi)容來(lái)自于ProGuard官方文檔以及各種博客等,相關(guān)文章的鏈接在參考目錄里,感...
    夷陵小祖閱讀 3,698評(píng)論 0 23
  • 內(nèi)容提要 本篇文章主要有三個(gè)部分,讓讀者讀完后能自己寫規(guī)則混淆項(xiàng)目 對(duì)Android代碼怎么開啟混淆做一個(gè)簡(jiǎn)單的介...
    一件小毛衣閱讀 7,866評(píng)論 2 73
  • 什么是代碼混淆 代碼混淆就是將代碼中的各種元素,如變量,方法,類和包的名字改寫成無(wú)意義的名字,增加項(xiàng)目反編譯后被讀...
    蝸牛家族史閱讀 5,191評(píng)論 1 4
  • Android 開發(fā)中為了代碼安全一般都會(huì)使用 ProGuard 進(jìn)行代碼混淆,它可以把類名、屬性名和方法名變?yōu)楹?..
    JohnnyShieh閱讀 4,292評(píng)論 2 13