為什麼要進行混淆
混淆是一種安全措施,防止在App釋出以後被人反編譯出來直接看到原始碼。做了混淆處理以後即使反編譯出來一些類名也變成了Class a,Class b之類的,增加了閱讀難度。
混淆以後就一定安全了嘛?
答案顯然是否定的。混淆只是增加了反編譯App的難度和成本,人家還是能看出你用了哪些開源庫,甚至一些業務邏輯。所以,其他的安全措施還是不能少,比如加密與服務端之前的資料請求等
用Android Studio怎麼設定混淆
- Android Studio已經整合了ProGuard作為混淆優化工具,只需要在gradle簡單設定即可開啟混淆
buildTypes {
release {
//開啟混淆
minifyEnabled true
//Zipalign優化
zipAlignEnabled true
// 移除無用的resource檔案
shrinkResources true
//前一部分代表系統預設的android程式的混淆檔案,該檔案已經包含了基本的混淆宣告
proguardFiles getDefaultProguardFile(`proguard-android.txt`), `proguard-rules.pro`
}
debug {
minifyEnabled false
zipAlignEnabled true
shrinkResources false
}
}
複製程式碼
- 上面的release版本設定minifyEnabled為true即表示開啟混淆,我們可以在proguard-rules.pro檔案中編輯混淆規則
- ProGuard有預設的混淆規則,而我們編輯的proguard-rules.pro檔案裡面除了一些ProGuard的設定,比如壓縮等級啊,輸出log啊,更多的是設定哪些東西不被混淆
- zipAlign可以讓安裝包中的資源按4位元組對齊,這樣可以減少應用在執行時的記憶體消耗。所以打包正式版最好也開啟。
哪些情況需要新增混淆規則
1.新增了一些有混淆規則要求的三方庫
- 比如圖片載入框架Glide,就需要新增以下規則,這些在官網的ProGuard標籤下可以找到
#Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.AppGlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
複製程式碼
- 網路庫Okhttp
#okhttp
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
複製程式碼
- 一個比較好的習慣是,每新增一個第三方庫到專案中,就在proguard-rules.pro檔案中新增對應的混淆規則
2.實現Parcelable和Serializable介面的類,比如一些需要持久化的實體類,不能混淆,需要新增混淆規則
- Parcelable的子類和Creator靜態成員變數不混淆
-keep class * implements Android.os.Parcelable { # 保持Parcelable不被混淆
public static final Android.os.Parcelable$Creator *;
}
複製程式碼
- 實現Serializable介面的類成員不能混淆
#保持所有實現 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();
public <fields>;
}
複製程式碼
3.與服務端互動,利用Gson、fastjson等框架解析所用的實體資料類不能混淆
-keep class com.myApp.test.bean.** { *; }
複製程式碼
這裡需要解釋一下上面的命令,*表示該包下面的類,**表示該包下面的類和子類,{ *; }表示類裡面的內容。所以上面的命令的意思就是保持com.myApp.test.bean包下面的類和子類不混淆,且類裡面的方法和變數也不混淆
4.jni方法不能混淆
-keepclasseswithmembernames class * { # 保持native方法不被混淆
native <methods>;
}
複製程式碼
keepclasseswithmembernames命令的意思是如果擁有某成員,保留類和類成員。以上的命令的意思就是說保留擁有native方法的類和類裡面的native方法不混淆
5.WebView的JS呼叫也需要保證寫的介面方法不混淆
- JS的介面方法可能是內部類,要保持內部類不被混淆,就需要用到符號$
# 保持MyWebView的內部類MyJavaScriptInterface不被混淆
-keep public class com..xxx.activity.MyWebView$MyJavaScriptInterface
# 保持MyWebView的內部類MyJavaScriptInterface中的所有public內容不被混淆
-keep public class com..xxx.activity.MyWebView$MyJavaScriptInterface {
public *;
}
複製程式碼
6.enum型別的2個特殊方法不能被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
複製程式碼
7.反射用的類不能被混淆
ProGuard常用的一些設定選項
#指定壓縮級別
-optimizationpasses 5
複製程式碼
#不跳過非公共的庫的類成員
-dontskipnonpubliclibraryclassmembers
複製程式碼
#輸出詳細日誌
-verbose
複製程式碼
#保留一些屬性,如行號LineNumberTable
-keepattributes LineNumberTable
複製程式碼
#優化時允許訪問並修改有修飾符的類和類的成員
-allowaccessmodification
複製程式碼
#忽略警告,一般有警告會編譯失敗,如果是一些無關緊要的警告可以忽略從而順利打包,否則要修復那些有問題的地方,以免App不能正常使用
-ignorewarnings
複製程式碼
#混淆時採用的演算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
複製程式碼
#優化時允許訪問並修改有修飾符的類和類的成員
-allowaccessmodification
複製程式碼
其他的一些設定及資訊,可以參考官網—ProGuard
今天你進步了嘛?歡迎關注我的微信公眾號,和我一起每天進步一點點!