前提
為了android應(yīng)用的安全性,往往我們在應(yīng)用發(fā)布之前都會(huì)進(jìn)行代碼混淆處理。以前都是網(wǎng)上了解大概,運(yùn)用網(wǎng)上寫好的混淆規(guī)則進(jìn)行修改。為了更加系統(tǒng)的學(xué)習(xí)混淆,現(xiàn)針對混淆做一個(gè)整理筆記。
混淆原理
android studio自帶java語言的ProGuard工具,主要用來壓縮、優(yōu)化、混淆,然后配合Gradle構(gòu)建工具實(shí)現(xiàn)混淆。
混淆步驟
1、在工程目錄下的gradle文件中設(shè)置release下的minifyEnabled=true。
buildTypes {
...
release {
minifyEnabled true
zipAlignEnabled false
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
1.minifyEnabled 表示是否打開混淆,true表示打開。
2.zipAlignEnabled是表示是否優(yōu)化。true表示打開,zipalign 是 Android 提供的一個(gè)整理優(yōu)化 apk 文件的工具,可在一定程度上上提高系統(tǒng)和應(yīng)用的運(yùn)行效率,更快的讀取 apk 中的資源,降低內(nèi)存的使用。
3.signingConfig signingConfigs.release配置簽名文件。
4.getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 配置混淆文件。
2、配置混淆文件。
a.基本語法詳解
#保持com.xiaohu.android包下的類名
-keep class com.xiaohu.android.*
#保持com.xiaohu.android包下以及子包下的類名
-keep class com.xiaohu.android.**
#保持類里面的方法和變量名不變
-keep class com.xiaohu.android.*{*;}
b.特殊語法
#保持類中部分內(nèi)容
# <init>; 匹配所有構(gòu)造器
# <fieids>; 匹配所有域
# <methods>; 匹配所有方法
#有時(shí)候我們需要在<fields>或<methods>前面加上private、public、native等訪問修飾符來指定不被混淆的內(nèi)容
#例如:表示Test類下所有的方法都不被混淆
-keep class com.xiaohu.android.Test{
public <methods>;
}
#表示用JSONObject作為入?yún)⒌臉?gòu)造函數(shù)不會(huì)被混淆
-keep class com.xiaohu.android.Test {
public <init>(org.json.JSONObject);
}
c.keep 與 keepclassmembers , keepclasseswithmembers簡介
d.通用語法、適合大部分項(xiàng)目
#指定壓縮級別
-optimizationpasses 5
#不跳過非公共的庫的類成員
-dontskipnonpubliclibraryclassmembers
#混淆時(shí)采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#把混淆類中的方法名也混淆了
-useuniqueclassmembernames
#優(yōu)化時(shí)允許訪問并修改有修飾符的類和類的成員
-allowaccessmodification
#將文件來源重命名為“SourceFile”字符串
-renamesourcefileattribute SourceFile
#假如項(xiàng)目中有用到注解,應(yīng)加入這行配置,對JSON實(shí)體映射也很重要,eg:fastjson
-keepattributes *Annotation*
#拋出異常時(shí)保留代碼行數(shù)
-keepattributes SourceFile,LineNumberTable
#保持泛型
-keepattributes Signature
#保持所有實(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中注冊,需要額外保護(hù)下
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment
#繼承activity,application,service,broadcastReceiver,contentprovider....不進(jìn)行混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.support.multidex.MultiDexApplication
-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.** {*;}
#自定義view
-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);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
#這個(gè)主要是在layout 中寫的onclick方法android:onclick="onClick",不進(jìn)行混淆
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
#保持枚舉
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#保持 Parcelable 不被混淆(aidl文件不能去混淆)
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持R文件不被混淆,否則,你的反射是獲取不到資源id的
-keep class **.R$* { *; }
# natvie 方法不混淆
-keepclasseswithmembernames class * {
native <methods>;
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#特殊配置
#保護(hù)WebView對HTML頁面的API不被混淆
#對WebView的簡單說明下:經(jīng)過實(shí)戰(zhàn)檢驗(yàn),做騰訊QQ登錄,如果引用他們提供的jar,
#若不加防止WebChromeClient混淆的代碼,oauth認(rèn)證無法回調(diào),反編譯基代碼后可看到他們有用到WebChromeClient,加入此代碼即可。
-keep class **.Webview2JsInterface { *; }
#如果你的項(xiàng)目中用到了webview的復(fù)雜操作,最好加入
-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.WebChromeClient {
public void *(android.webkit.WebView,java.lang.String);
}
#轉(zhuǎn)換JSON的JavaBean,類成員名稱保護(hù),使其不被混淆
-keepclassmembernames class com.xiaohu.android.bean.** { *; }
# 保持測試相關(guān)的代碼
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**