Android混淆機(jī)制

如何開啟混淆

eclipse

只需要在工程中找到projiect.properties文件,在這個(gè)文件中修改下面一段代碼:

proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

Android Studio

在對(duì)應(yīng)的module中,找到build.gradle,在該文件中找到buildTypes,將minifyEnabled置成true,(有對(duì)gradle不熟悉的同學(xué),可以參考這篇文章Android工程gradle詳解):

release {//release對(duì)應(yīng)release編譯,debug對(duì)應(yīng)debug編譯

// 是否進(jìn)行混淆

minifyEnabled true

// 簽名文件

signingConfig signingConfigs.debug

//對(duì)應(yīng)的混淆文件

proguardFiles 'proguard-rules.pro'

}

Proguard

Proguard是Android常用的免費(fèi)的混淆工具,如果想了解混淆,需要先對(duì)Proguard進(jìn)行了解

功能

Proguard主要提供了如下四種功能:

  • 壓縮:Java源代碼通常被編譯為字節(jié)碼,雖然字節(jié)碼比源代碼更加簡(jiǎn)潔,但它本身仍包含了很多無用的代碼,Proguard通過分析字節(jié)碼,去掉冗余代碼。
  • 優(yōu)化: 優(yōu)化Java字節(jié)碼,移除沒有使用到的指令
  • 混淆: 使用無意義的字母對(duì)類名方法名,字段名進(jìn)行重命名,達(dá)到混淆的效果
  • 預(yù)檢驗(yàn): 對(duì)上述處理的代碼進(jìn)行與監(jiān)獄

基本配置

-dontusemixedcaseclassnames//不使用大小寫形式的混淆名
-dontskipnonpubliclibraryclasses//不跳過library的非public的類
-dontoptimize//不進(jìn)行優(yōu)化,優(yōu)化可能會(huì)在某些手機(jī)上無法運(yùn)行。
-dontpreverify//不凈行預(yù)校驗(yàn),該校驗(yàn)是java平臺(tái)上的,對(duì)android沒啥用處
-keepattributes *Annotation*//對(duì)注解中的參數(shù)進(jìn)行保留
-keep public class com.deep.test.MainActivity //對(duì)某個(gè)class不進(jìn)行混淆
-dontshrink //不縮減代碼,需要注意,反射調(diào)用的代碼會(huì)被認(rèn)為是無用代碼而刪掉,所以要提前keep出來
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}//保持枚舉類中的屬性不被混淆
-keepclassmemberspublic class xxx extends xxx{
void set*(***);
*** get*();
}不混淆任何view子類的get和set方法。
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}//aidl文件不能去混淆
-keep public class com.ebt.app.common.bean.Customer
//保留某個(gè)類名不被混淆
-keep public class com.ebt.app.common.bean.Customer { *;}
//保留類及其所有成員不被混淆
-keep public class com.ebt.app.common.bean.Customer {
static final;
private void get*();
}//只保留類名及其部分成員不被混淆
-keep class com.ebt.app.sync.** { *;}
//保留包路徑下所有的類及其屬性和方法
-keepclassmembers class **.R$* {
public static ;
}//資源類變量需要保留

下面會(huì)對(duì)上面提到過的關(guān)鍵字進(jìn)行介紹:

  • keep:包留類和類中的成員,防止他們被混淆
  • keepnames:保留類和類中的成員防止被混淆,但成員如果沒有被引用將被刪除
  • keepclassmembers:只保留類中的成員,防止被混淆和移除。
  • keepclassmembernames:只保留類中的成員,但如果成員沒有被引用將被刪除。
  • keepclasseswithmembers:如果當(dāng)前類中包含指定的方法,則保留類和類成員,否則將被混淆。
  • keepclasseswithmembernames:如果當(dāng)前類中包含指定的方法,則保留類和類成員,如果類成員沒有被引用,則會(huì)被移除。
  • -dontwarn:忽視警告。
  • -optimizationpasses 5:proguard對(duì)你的代碼進(jìn)行迭代優(yōu)化的次數(shù),首先要明白o(hù)ptimization 會(huì)對(duì)代碼進(jìn)行各種優(yōu)化,每次優(yōu)化后的代碼還可以再次優(yōu)化,所以就產(chǎn)生了 優(yōu)化次數(shù)的問題,這里面的 passes 應(yīng)該翻譯成 ‘次數(shù)’
  • -keepattributes Signature:避免混淆泛型。
  • -keepattributes SourceFile,LineNumberTable:拋出異常時(shí)保留代碼行號(hào)

一些符號(hào)的解釋說明

<init>構(gòu)造方法
<field>所有成員
<methods>所有方法

所以所有成員不被混淆可以這么寫


-keepclasseswithmembers class com.ebt.app.common.bean.Customer {

<init>;

<field>;

<methods>;

}

你還可以在<fields>或<methods>前面加上private 、public、native等來進(jìn)一步指定不被混淆的內(nèi)容:


-keepclasseswithmembers class com.ebt.app.common.bean.Customer {

public  <init>;

public  <field>;

public  <methods>;

}

還可以再加一些限制(以JSONObject類型作為參數(shù)的構(gòu)造方法不進(jìn)行混淆):

-keepclasseswithmembers class com.ebt.app.common.bean.Customer {

public <init>(org.json.JSONObject);
}

防止jni的方法被混淆

-keepclasseswithmembernames class * { # 保持native方法不被混淆
native <methods>;
}


* $如果我們要保留一個(gè)類中的內(nèi)部類不被混淆則需要用$符號(hào)
* ?  匹配單一的字符

* *匹配一段字符

* %匹配基本類型

* -libraryjars libs/aaa.jar 不混淆某個(gè)jar
##注意事項(xiàng)
* 反射用到的類不混淆(否則反射可能出現(xiàn)問題);
* AndroidMainfest中的類不混淆,所以四大組件和Application的子類和Framework層下所有的類默認(rèn)不會(huì)進(jìn)行混淆。自定義的View默認(rèn)也不會(huì)被混淆;所以像網(wǎng)上貼的很多排除自定義View,或四大組件被混淆的規(guī)則在Android Studio中是無需加入的;
* 與服務(wù)端交互時(shí),使用GSON、fastjson等框架解析服務(wù)端數(shù)據(jù)時(shí),所寫的JSON對(duì)象類不混淆,否則無法將JSON解析成對(duì)應(yīng)的對(duì)象;
* 使用第三方開源庫或者引用其他第三方的SDK包時(shí),如果有特別要求,也需要在混淆文件中加入對(duì)應(yīng)的混淆規(guī)則;
* 有用到WebView的JS調(diào)用也需要保證寫的接口方法不混淆;
* Parcelable的子類和Creator靜態(tài)成員變量不混淆,否則會(huì)產(chǎn)生Android.os.BadParcelableException異常

-keep class * implements Android.os.Parcelable { # 保持Parcelable不被混淆
public static final Android.os.Parcelable$Creator *;
}

* 使用enum類型時(shí)需要注意避免以下兩個(gè)方法混淆,因?yàn)閑num類的特殊性,以下兩個(gè)方法會(huì)被反射調(diào)用,見第二條規(guī)則。

-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容