ProGuard是一個開源的Java代碼混淆器。它能夠混淆Android項目裏面的java代碼,對的,你沒看錯,僅僅是java代碼。它是沒法混淆Native代碼,資源文件drawable、xml等。php
壓縮: 移除無效的類、屬性、方法等html
優化: 優化字節碼,並刪除未使用的結構java
混淆: 將類名、屬性名、方法名混淆爲難以讀懂的字母,好比a,b,clinux
在AndroidManifest中配置的類,好比四大組件android
JNI調用的方法git
反射用到的類github
WebView中JavaScript調用的方法app
Layout文件引用到的自定義Viewide
一些引入的第三方庫(通常都會有混淆說明的)
這裏推薦兩個開源項目,裏面收集了一些第三方庫的混淆規則工具
不難理解,混淆以後,類名會變成a,b,c這種,經過包名+類名天然就會找不到該類了,天然就會出現ClassNotFoundException異常。這裏推薦一篇文章:
http://www.itnose.net/detail/6043297.html
咱們都知道,使用Log的時候,須要用到TAG,然而TAG咱們通常都會寫成: private static final String TAG = MainActivity.class.getSimpleName()
這時候MainActivity如何被混淆的話,log輸出信息就會變成V/a:xxxxxxx,因此爲了讓log輸出信息維持原狀,能夠將TAG處理成固定的字符串: private static final String TAG = "MainActivity"
正好Android Studio裏面的Live Templates
能讓你輕輕鬆鬆的聲明TAG
關於Log處理,推薦一篇文章:https://www.zybuluo.com/shark0017/note/163330
代碼混淆的時候記得加上在混淆文件裏面記得加上這句: # keep住源文件以及行號
-keepattributes SourceFile,LineNumberTable
不然你看到的崩潰信息就會變成這樣子(圖片來自bugly)
這裏推薦bugly的一篇文章: http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=26&extra=page%3D1
保留
-keep {Modifier} {class_specification} 保護指定的類文件和類的成員
-keepclassmembers {modifier} {class_specification} 保護指定類的成員,若是此類受到保護他們會保護的更好
-keepclasseswithmembers {class_specification} 保護指定的類和類的成員,但條件是全部指定的類和類成員是要存在。
-keepnames {class_specification} 保護指定的類和類的成員的名稱(若是他們不會壓縮步驟中刪除)
-keepclassmembernames {class_specification} 保護指定的類的成員的名稱(若是他們不會壓縮步驟中刪除)
-keepclasseswithmembernames {class_specification} 保護指定的類和類的成員的名稱,若是全部指定的類成員出席(在壓縮步驟以後)
-printseeds {filename} 列出類和類的成員-keep選項的清單,標準輸出到給定的文件
壓縮
-dontshrink 不壓縮輸入的類文件
-printusage {filename}
-whyareyoukeeping {class_specification}
優化
-dontoptimize 不優化輸入的類文件
-assumenosideeffects {class_specification} 優化時假設指定的方法,沒有任何反作用
-allowaccessmodification 優化時容許訪問並修改有修飾符的類和類的成員
混淆
-dontobfuscate 不混淆輸入的類文件
-obfuscationdictionary {filename} 使用給定文件中的關鍵字做爲要混淆方法的名稱
-overloadaggressively 混淆時應用侵入式重載
-useuniqueclassmembernames 肯定統一的混淆類的成員名稱來增長混淆
-flattenpackagehierarchy {package_name} 從新包裝全部重命名的包並放在給定的單一包中
-repackageclass {package_name} 從新包裝全部重命名的類文件中放在給定的單一包中
-dontusemixedcaseclassnames 混淆時不會產生形形色色的類名
-keepattributes {attribute_name,…} 保護給定的可選屬性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.
-renamesourcefileattribute {string} 設置源文件中給定的字符串常量
通配符匹配規則
通配符 | 規則 |
---|---|
? | 匹配單個字符 |
* | 匹配類名中的任何部分,但不包含額外的包名 |
** | 匹配類名中的任何部分,而且能夠包含額外的包名 |
% | 匹配任何基礎類型的類型名 |
* | 匹配任意類型名 ,包含基礎類型/非基礎類型 |
... | 匹配任意數量、任意類型的參數 |
<init> | 匹配任何構造器 |
<ifield> | 匹配任何字段名 |
<imethod> | 匹配任何方法 |
*(當用在類內部時) | 匹配任何字段和方法 |
$ | 指內部類 |
更詳細的語法請戳:http://proguard.sourceforge.net/manual/usage.html#classspecification
按照上面的語法規則編寫proguard-rules.pro後,須要在build.gradle中配置,須要混淆的時候,設置minifyEnabled爲true便可
buildTypes { debug { minifyEnabled false } release { signingConfig signingConfigs.release minifyEnabled true proguardFiles 'proguard-rules.pro' } }
混淆後,會在/build/proguard/目錄下輸出下面的文件
dump.txt 描述apk文件中全部類文件間的內部結構。
mapping.txt 列出了原始的類,方法,和字段名與混淆後代碼之間的映射。
seeds.txt 列出了未被混淆的類和成員
usage.txt 列出了從apk中刪除的代碼
當咱們須要處理crash log的時候,就能夠經過mapping.txt的映射關係找到對應的類,方法,字段等。方法以下:
sdk\tools\proguard\bin 目錄下有個retrace工具能夠將混淆後的報錯堆棧解碼成正常的類名
window下爲retrace.bat,linux和mac爲retrace.sh,
使用方法以下:
將crash log保存爲yourfilename.txt
拿到版本發佈時生成的mapping.txt
執行命令retrace.bat -verbose mapping.txt yourfilename.txt
因此咱們每次打包版本都須要保存最新的mapping.txt文件。若是要使用到第三方的crash統計平臺,好比bugly,還須要咱們上傳APP版本對應的mapping.txt.每次都要保存最新的mapping文件,那不就很麻煩?放心,gradle會幫到你,只須要在bulid.gradle加入下面的一句。每次咱們編譯的時候,都會自動幫你保存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" } } } } } ...... } }
https://blog.gmem.cc/proguard-study-note
http://developer.android.com/intl/zh-cn/tools/help/proguard.html
打個小廣告,推薦下本身的:Android-Dev-Favorites,裏面收集了Android開發的乾貨,而且會不按期更新哦。