自定義 Android Gradle -- 使用混淆

----《Android Gradle 權(quán)威指南》學(xué)習(xí)筆記

總目錄:Gradle 學(xué)習(xí)系列 -- 目錄

上一篇:自定義 Android Gradle -- 隱藏簽名文件信息

下一篇:自定義 Android Gradle -- 啟動(dòng) zipalign 優(yōu)化

1. 簡介

代碼混淆時(shí)一個(gè)非常有用的功能叛薯,它不僅能優(yōu)化代碼,讓 apk 包變得更小传蹈,還可以混淆原來的代碼,讓反編譯的人不容易看明白業(yè)務(wù)邏輯妆艘,很難分析北启。一般情況下發(fā)布到市場的版本是要混淆的。調(diào)試的版本不用混淆遏乔,因?yàn)榛煜缶蜔o法斷點(diǎn)跟蹤調(diào)試了式曲。

2. 開啟混淆

要啟用混淆妨托,只需把 BuildType 的屬性 miniEnabled 的值設(shè)置為 true 即可:

buildTypes {
        release {
            ......
            minifyEnabled true
        }
    }

3. Proguard 配置

開啟了代碼混淆之后,Android Gradle 還不知道按何種規(guī)則進(jìn)行混淆吝羞,不知道要保留哪些類不混淆兰伤,要做到這些就需要 Proguard 配置文件了。指定 Proguard 配置文件可以使用 proguardFile 方法钧排,也可以使用 proguardFiles 方法敦腔。這個(gè)根據(jù)實(shí)際情況而定,看是需要指定一個(gè)還是想同時(shí)指定多個(gè)恨溜。

4. 默認(rèn)的 Proguard 配置文件

AndroidStudio 中默認(rèn)指定了 Proguard 配置文件:

buildTypes {
        release {
            ......
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

proguardFiles 加載了兩個(gè)文件:getDefaultProguardFile(‘proguard-android.txt’)表示默認(rèn)文件符衔,這個(gè)文件是 sdk 自帶的,有一些通用的配置糟袁;但是如果 apk 需要更加嚴(yán)格的加密判族,可以在 proguard-rules.pro 文件中進(jìn)行更加詳盡的配置。
其中:

  • proguard-android.txt 文件在 SDK 中项戴,具體的路徑為:${sdk}\tools\proguard\
  • 在SDK 中形帮,還有一個(gè)配置文件:proguard-android-optimize.txt,一個(gè)是沒有優(yōu)化的肯尺,一個(gè)是優(yōu)化的。
  • proguard-rules.pro 文件在 AndroidStudio 工程中躯枢,和 app 工程的 build.gradle 同級(jí)则吟,如圖:
    7.7.png

5. proguard-android.txt 內(nèi)容

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

# 包名不混合大小寫
-dontusemixedcaseclassnames
# 不忽略非公共的庫類
-dontskipnonpubliclibraryclasses
# 輸出混淆日志
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
# 不進(jìn)行優(yōu)化
-dontoptimize
# 不進(jìn)行預(yù)檢驗(yàn)
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

# 不混淆注解(注解不能被混淆)
-keepattributes *Annotation*
# 不混淆指定類
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
# 不混淆native的方法
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
# 不混淆繼承View的所有類的set和get方法
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
# 不混淆繼承Activity的所有類的中的參數(shù)類型為View的方法
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
# 不混淆枚舉類型的values和valueOf方法
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 不混淆繼承Parcelable的所有類的CREATOR
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

# 不混淆R類中所有static字段
-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
# 忽略兼容庫的所有警告
-dontwarn android.support.**

# Understand the @Keep support annotation.
# 不混淆指定的類及其類成員
-keep class android.support.annotation.Keep

# 不混淆使用注解的類及其類成員
-keep @android.support.annotation.Keep class * {*;}

# 不混淆所有類及其類成員中的使用注解的方法
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

# 不混淆所有類及其類成員中的使用注解的字段
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

# 不混淆所有類及其類成員中的使用注解的初始化方法
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}

從上面的解析可以看出,proguard-android.txt 中只提供了基本的內(nèi)容锄蹂,在實(shí)際使用 ProGuard 時(shí)通常需要配置大量的規(guī)則氓仲。例如,引用的第三方庫的混淆配置,不混淆自定義控件敬扛,不混淆反射的類等晰洒。

6. proguard-android.txt 中的基礎(chǔ)語法:

-include {filename}    從給定的文件中讀取配置參數(shù)   
-basedirectory {directoryname}    指定基礎(chǔ)目錄為以后相對的檔案名稱   
-injars {class_path}    指定要處理的應(yīng)用程序jar,war,ear和目錄   
-outjars {class_path}    指定處理完后要輸出的jar,war,ear和目錄的名稱   
-libraryjars {classpath}    指定要處理的應(yīng)用程序jar,war,ear和目錄所需要的程序庫文件   
-dontskipnonpubliclibraryclasses    指定不去忽略非公共的庫類。   
-dontskipnonpubliclibraryclassmembers    指定不去忽略包可見的庫類的成員啥箭。  

保留選項(xiàng)   
-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è)指定的方法坏怪,沒有任何副作用   
-allowaccessmodification    優(yōu)化時(shí)允許訪問并修改有修飾符的類和類的成員   

混淆   
-dontobfuscate    不混淆輸入的類文件   
-printmapping {filename}   
-applymapping {filename}    重用映射增加混淆   
-obfuscationdictionary {filename}    使用給定文件中的關(guān)鍵字作為要混淆方法的名稱   
-overloadaggressively    混淆時(shí)應(yīng)用侵入式重載   
-useuniqueclassmembernames    確定統(tǒng)一的混淆類的成員名稱來增加混淆   
-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è)置源文件中給定的字符串常量  

7. 關(guān)鍵字包括:

  • keep 保留類和類中的成員,防止它們被混淆或者移除
  • keepnames 保留類和類中的成員铝宵,防止它們被混淆打掘,但當(dāng)成員沒有被引用時(shí)會(huì)被移除
  • keepclassmembers 只保留類中的成員,防止它們被混淆或者移除
  • keepclassmembernames 只保留類中的成員鹏秋,防止它們被混淆,但當(dāng)成員沒有被引用時(shí)會(huì)被移除
  • keepclasswithmembers 保留類和類中的成員尊蚁,防止它們被混淆或者移除,前提是指名的類中的成員必須存在拼岳,如果不存在則還是會(huì)混淆
  • keepclasswithmembernames 保留類和類中的成員枝誊,防止它們被混淆,但當(dāng)成員沒有被引用時(shí)會(huì)被移除惜纸,前提是指名的類中的成員必須存在叶撒,如果不存在則還是會(huì)混淆

8. 通配符包括:

field 匹配類中的所有字段
method 匹配類中的所有方法
init 匹配類中的所有的構(gòu)造函數(shù)
* 匹配任意長度字符,但不含包名分隔符(.),比如說我們的完整類名是com.example.test.MainActivtiy,使用com.*,或者com.example.*耐版,都是無法匹配的祠够,因?yàn)?無法匹配包名中的分隔符,正確的匹配方式是com.example.*.*粪牲,或者是com.example.test.*古瓤,這些都是可以的。但如果你不寫任何其他內(nèi)容腺阳,只有一個(gè)*,那就表示匹配所有的東西
**匹配任意長度字符落君,并且含包名分隔符(.),比如android.support.**就可以匹配android.support包下所有的內(nèi)容,包括任意長度的子包.
***匹配任意參數(shù)類型亭引,比如void set(***)就能匹配任意傳入的參數(shù)類型绎速,*** get*()就能匹配任意返回值的類型
… 匹配任意長度的任意參數(shù)類型,比如void set(…)就能匹配任意的void set(String a)或者是void set(String a焙蚓,int b)等方法

9. 注意點(diǎn):

  • Java的反射不能混淆纹冤。因?yàn)榇a混淆洒宝,類名、方法名萌京、屬性名都改變了雁歌,而反射它還是按照原來的名字去反射。
  • 注解用了反射知残,所以不能混淆靠瞎。
  • 不混淆任何包含native方法的類的類名以及native方法名,否則找不到本地方法橡庞。
  • Activity更不能混淆较坛,因?yàn)锳ndroidManifest.xml文件中是完整的名字,混淆后怎么找扒最?
  • 自定義view也是帶了包名寫在xml布局中丑勤,給我換成a,怎么破吧趣? R文件混淆了法竞,id沒了,界面崩潰那時(shí)自然咯强挫。
  • 一般在使用第三方框架岔霸,sdk時(shí)主要其給出的混淆方案。github第三方混淆方案

10. 輸出文件

每次構(gòu)建時(shí) ProGuard 都會(huì)輸出下列文件:

  • dump.txt 說明 APK 中所有類文件的內(nèi)部結(jié)構(gòu)俯渤。
  • mapping.txt 提供原始與混淆過的類呆细、方法和字段名稱之間的轉(zhuǎn)換。
  • seeds.txt 列出未進(jìn)行混淆的類和成員八匠。
  • usage.txt 列出從 APK 移除的代碼絮爷。
    這些文件保存在 modulename/build/outputs/mapping/release/ 中。
相關(guān)代碼:https://gitee.com/fzq.com/gradle-demos
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末梨树,一起剝皮案震驚了整個(gè)濱河市坑夯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌抡四,老刑警劉巖柜蜈,帶你破解...
    沈念sama閱讀 212,294評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異指巡,居然都是意外死亡淑履,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門藻雪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秘噪,“玉大人,你說我怎么就攤上這事阔涉±峦蓿” “怎么了?”我有些...
    開封第一講書人閱讀 157,790評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵瑰排,是天一觀的道長贯要。 經(jīng)常有香客問我,道長椭住,這世上最難降的妖魔是什么崇渗? 我笑而不...
    開封第一講書人閱讀 56,595評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮京郑,結(jié)果婚禮上宅广,老公的妹妹穿的比我還像新娘。我一直安慰自己些举,他們只是感情好跟狱,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,718評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著户魏,像睡著了一般驶臊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叼丑,一...
    開封第一講書人閱讀 49,906評(píng)論 1 290
  • 那天关翎,我揣著相機(jī)與錄音,去河邊找鬼鸠信。 笑死纵寝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的星立。 我是一名探鬼主播爽茴,決...
    沈念sama閱讀 39,053評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贞铣!你這毒婦竟也來了闹啦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,797評(píng)論 0 268
  • 序言:老撾萬榮一對情侶失蹤辕坝,失蹤者是張志新(化名)和其女友劉穎窍奋,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酱畅,經(jīng)...
    沈念sama閱讀 44,250評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡琳袄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,570評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纺酸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窖逗。...
    茶點(diǎn)故事閱讀 38,711評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖餐蔬,靈堂內(nèi)的尸體忽然破棺而出碎紊,到底是詐尸還是另有隱情佑附,我是刑警寧澤,帶...
    沈念sama閱讀 34,388評(píng)論 4 332
  • 正文 年R本政府宣布仗考,位于F島的核電站音同,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏秃嗜。R本人自食惡果不足惜权均,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,018評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锅锨。 院中可真熱鬧叽赊,春花似錦、人聲如沸必搞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恕洲。三九已至取劫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間研侣,已是汗流浹背谱邪。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留庶诡,地道東北人惦银。 一個(gè)月前我還...
    沈念sama閱讀 46,461評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像末誓,于是被迫代替她去往敵國和親扯俱。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,595評(píng)論 2 350

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