Proguard介紹
Proguard定義
對于ProGuard工具想必我們都不陌生氛堕,它能夠通過移除無用代碼馏臭,使用簡短無意義的名稱來重命名類,字段和方法讼稚。從而能夠達到壓縮括儒、優(yōu)化和混淆代碼的目的。最終我們會獲取一個較小的apk文件锐想,并且我們這個通過ProGuard處理的apk文件更難于進行逆向工程帮寻。
ProGuard能夠?qū)ava類中的代碼進行壓縮(Shrink),優(yōu)化(Optimize),混淆(Obfuscate),預(yù)檢(Preveirfy)。
- 壓縮(Shrink):在壓縮處理這一步中痛倚,用于檢測和刪除沒有使用的類规婆,字段,方法和屬性蝉稳。
- 優(yōu)化(Optimize):在優(yōu)化處理這一步中抒蚜,對字節(jié)碼進行優(yōu)化,并且移除無用指令耘戚。
- 混淆(Obfuscate):在混淆處理這一步中嗡髓,使用a,b,c等無意義的名稱,對類收津,字段和方法進行重命名饿这。
- 預(yù)檢(Preveirfy):在預(yù)檢這一步中,主要是在Java平臺上對處理后的代碼進行預(yù)檢撞秋。
Proguard使用
- 將proguard添加到build.gradle的buildTypes中
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
minifyEnabled:開啟混淆,我們新建的工程默認(rèn)為false长捧,因此,如果我們需要開啟混淆的話就需要手動設(shè)為true吻贿。
proguardFiles:這部分有兩段串结,前一段代表系統(tǒng)默認(rèn)的android程序的混淆文件,該文件已經(jīng)包含了基本的混淆聲明舅列,免去了我們很多事肌割,這個文件的目錄在/tools/proguard/proguard-android.txt , 后一部分是我們項目里的自定義的混淆文件,目錄就在 app/proguard-rules.pro,在這個文件里我們可以聲明一些我們所需要的定制的混淆規(guī)則帐要。
Proguard模板代碼(Android)
#############################################
#
# 對于一些基本指令的添加
#
#############################################
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-optimizations !code/simplification/cast,!field/*,!class/merging/*
#############################################
#
# Android開發(fā)中一些需要保留的公共部分
#
#############################################
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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 public class com.android.vending.licensing.ILicensingService
-keep class android.support.** {*;}
-keep class **.R$* {*;}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclassmembers class * extends android.app.Activity{
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-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);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-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();
}
-keepclassmembers class * {
void *(**On*Event);
}
#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);
}
#############################################
#
# 項目中特殊處理部分
#
#############################################
#-----------處理反射類---------------
......
#-----------處理js交互---------------
......
#-----------處理實體類---------------
......
#-----------處理第三方依賴庫---------
......
針對App的特殊配置
- 處理反射類
-keep class 類所在的包.** { *; }
- 處理js交互
App中有時需要與HTML5中的JavaScript交互,例如:
package com.ljd.example;
public class JSInterface {
@JavascriptInterface
public void callAndroidMethod(){
// do something
}
}
要確保這些js要調(diào)用的原生方法不能夠被混淆
-keepclassmembers class com.ljd.example.JSInterface {
<methods>;
}
- 處理實體類
-keep public class com.ljd.example.entity.** {
public void set*(***);
public *** get*();
public *** is*();
}
將所有實體類放在一處
- keep class com.ljd.example.entity.** { *; }
- 處理第三方類庫
取決于第三方的混淆策略榨惠,列舉一些如下:
#支付寶
-libraryjars libs/alipaysdk.jar
-dontwarn com.alipay.android.app.**
-keep public class com.alipay.** { *; }
# Retrolambda
-dontwarn java.lang.invoke.*
#realm
-keep class io.realm.annotations.RealmModule
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep @io.realm.internal.Keep class * { *; }
-dontwarn javax.**
-dontwarn io.realm.**
# OrmLite
-keep class com.j256.**
-keepclassmembers class com.j256.** { *; }
-keep enum com.j256.**
-keepclassmembers enum com.j256.** { *; }
-keep interface com.j256.**
-keepclassmembers interface com.j256.** { *; }
#極光推送
-dontoptimize
-dontpreverify
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
#EventBus
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
#retroift
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
#ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
#fastjson
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.** { *; }
#rxjava
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
#jackson
-dontwarn org.codehaus.jackson.**
-dontwarn com.fasterxml.jackson.databind.**
-keep class org.codehaus.jackson.** { *;}
-keep class com.fasterxml.jackson.** { *; }
#Facebook
-keep class com.facebook.** {*;}
-keep interface com.facebook.** {*;}
-keep enum com.facebook.** {*;}
#Fresco
-keep class com.facebook.fresco.** {*;}
-keep interface com.facebook.fresco.** {*;}
-keep enum com.facebook.fresco.** {*;}
Proguard vs Dexguard
Proguard優(yōu)點
- 免費奋早,已經(jīng)集成在Android ADT中盛霎,使用方便
Proguard缺點
- 可以使用apktool工具反編譯出資源,能夠看到Manifest文件耽装,res資源等等摩渺。也可以使用dex2jar工具生成jar文件,進而使用jd工具反編譯出Java代碼片段剂邮。雖然,這些代碼大部分都經(jīng)過了混淆横侦,已經(jīng)很難閱讀挥萌,但是還是可以讀的。
- Proguard只能保護代碼枉侧,卻不能保護我們的apk文件引瀑。任何人都可以使用apktool工具,反編譯我們開發(fā)的apk文件榨馁,進而更改其中各種資源憨栽,或者更改部分代碼,甚至是注入代碼翼虫,然后再打包回apk屑柔,二次發(fā)布后,達到自己的目的珍剑〉穑或者是加入了廣告,或者是增加了惡意木馬病毒招拙,等等唧瘾。
Dexguard優(yōu)點
- DexGuard是在Proguard基礎(chǔ)上,加入了更多的保護措施别凤。使用DexGuard混淆后饰序,生成的apk文件,就無法正常使用apktool反編譯了规哪。盡管還是能夠反編譯出部分資源文件求豫,但是由于反編譯過程不完全,就無法再打包成apk了由缆。這樣就保護了我們的apk文件注祖,不會被二次打包發(fā)布了。
Dexguard缺點
- 收費