前言
正常一個APP都會開啓混淆,但是有時後接手的項目並沒有開啓混淆,然後自己修改的時候就很蛋疼,因爲開啓混淆便會報錯,如果有一些沒有用過的第三方庫更要自己去處理,這裏就記錄一下安卓常見的混淆文件和常規用法。
混淆好處以及哪些是不能混淆的
面試常問混淆好處,我們張口就來:
- 打包時會去掉無用資源有效減少APK體積(尤其對一些開發不規範導致很多無效代碼和資源文件)其實這也可以變向的解決64k問題
- 增加反編譯成本,有效提高APK安全性(其實很多APK都會用第三方加密工具如360、愛加密)
但是並不是什麼都可以混淆的:(具體配置代碼都有)
- 實體類
- 序列化對象
- 反射
- 枚舉
- resource
- native方法(像java調用c++)
- 一些自定義控件
- Gson對象
開啓混淆
buildTypes {
debug {
// 顯示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
minifyEnabled false//是否開啓混淆
zipAlignEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//加載的混淆文件
signingConfig signingConfigs.debug
}
release {
// 不顯示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
minifyEnabled true//是否開啓混淆
zipAlignEnabled true
// 移除無用的resource文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//混淆文件位置
signingConfig signingConfigs.release
}
}
可以看到其實是否開啓混淆通過:
minifyEnabled true//是否開啓混淆
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’//混淆文件位置
但是你開啓混淆會打包很慢的所以這裏一定要區分當前打包模式是:debug還是release,一般debug打包提供測試用,我們不會開啓混淆。
如何打簽名包
通過AS工具面板Build ---->Generate Singned Bundle or APK
我們選擇apk後,輸入好籤名密碼:
這裏如果你設置渠道包的話會選擇當前渠道,我這就簡單選擇release點擊finish便可。
混淆文件配置
重頭戲來啦,在android中常用的混淆文件(可以複製我這個常用的然後再添加)
指定代碼的壓縮級別
-optimizationpasses 5
#包明不混合大小寫
-dontusemixedcaseclassnames
#不去忽略非公共的庫類
-dontskipnonpubliclibraryclasses
#優化 不優化輸入的類文件
-dontoptimize
#預校驗
-dontpreverify
#混淆時是否記錄日誌
-verbose
# 混淆時所採用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保護註解
-keepattributes *Annotation*
#如果有引用v4包可以添加下面這行
-keep public class * extends android.support.v4.app.Fragment
#忽略警告
-ignorewarning
##記錄生成的日誌數據,gradle build時在本項目根目錄輸出##
#apk 包內所有 class 的內部結構
-dump proguard/class_files.txt
#未混淆的類和成員
-printseeds proguard/seeds.txt
#列出從 apk 中刪除的代碼
-printusage proguard/unused.txt
#混淆前後的映射
-printmapping proguard/mapping.txt
########記錄生成的日誌數據,gradle build時 在本項目根目錄輸出-end######
#如果引用了v4或者v7包
-dontwarn android.support.**
#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
#保持自定義控件類不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
#保持自定義控件類不被混淆
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持 Serializable 不被混淆
-keepnames class * implements java.io.Serializable
#保持 Serializable 不被混淆並且enum 類也不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#保持枚舉 enum 類不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * {
public void *ButtonClicked(android.view.View);
}
#不混淆資源類
-keepclassmembers class **.R$* {
public static <fields>;
}
#避免混淆泛型 如果混淆報錯建議關掉
-keepattributes Signature
#移除Log類打印各個等級日誌的代碼,打正式包的時候可以做爲禁log使用,這裏可以作爲禁止log打印的功能使用,另外的一種實現方案是通過BuildConfig.DEBUG的變量來控制
#-assumenosideeffects class android.util.Log {
# public static *** v(...);
# public static *** i(...);
# public static *** d(...);
# public static *** w(...);
# public static *** e(...);
#}
#-------------------------------------------定製化區域----------------------------------------------
#---------------------------------1.實體類---------------------------------
-keep class 自己項目的包名.bean.** { *; }
#########################################################第三方的配置開始#######################
############shareSDK混淆配置################
-keep class cn.sharesdk.**{*;}
-keep class com.sina.**{*;}
-keep class **.R$* {*;}
-keep class **.R{*;}
-keep class com.mob.**{*;}
#####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);
}
###########極光混淆配置
-dontoptimize
-dontpreverify
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; }
-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }
###########okhttputils 和okhttp相關的 的混淆####################
#okhttputils
-dontwarn com.zhy.http.**
-keep class com.zhy.http.**{*;}
#okhttp
-dontwarn okhttp3.**
-keep class okhttp3.**{*;}
#okio
-dontwarn okio.**
-keep class okio.**{*;}
-dontwarn com.squareup.okhttp.**
-dontwarn javax.annotation.**
-dontwarn com.android.volley.toolbox.**
-dontwarn com.facebook.infer.**
-keep class com.squareup.okhttp.** { *;}
-keep interface com.squareup.okhttp.** { *; }
######################### Retrofit混淆配置##############################
-dontnote retrofit2.Platform
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
-dontwarn retrofit2.Platform$Java8
-keepattributes Signature
-keepattributes Exceptions
#########################友盟的混淆配置################
-keep class com.umeng.** {*;}
-keepclassmembers class * {
public <init> (org.json.JSONObject);
}
-keepclassmembers class * {
public <init>(org.json.JSONObject);
}
-keep public class [com.uutus.huaxia.geography].R$*{
public static final int *;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep public class [com.uutus.huaxia.geography].R$*{
public static final int *;
}
###############加密混淆###########
########騰訊X5內核瀏覽器中的的代碼不被混淆#####
-keep class com.tencent.** {*;}
########RSA中的代碼不被混淆
-keep class Decoder.** {*;}
-keep class org.bouncycastle.** {*;}
################Glide加載圖片添加混淆
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
######## glide類庫
######## com.github.bumptech.glide:okhttp3-integration:1.4.0@aar中的代碼不被混淆
######## jp.wasabeef:glide-transformations:2.0.1 不被混淆
-keep class com.bumptech.** {*;}
-keep class jp.wasabeef.glide.** {*;}
########## 保證類庫Image 中導入的jar包不被混淆
-keep class com.davemorrissey.** {*;}
-keep class com.filippudak.** {*;}
-keep class am.util.** {*;}
-keep class com.blankj.** {*;}
#########################################################第三方的配置結束#######################
#==================gson && protobuf==========================
-dontwarn com.google.**
-keep class com.google.gson.** {*;}
-keep class com.google.protobuf.** {*;}
#ProGuard 混淆
# keep住源文件以及行號
-keepattributes SourceFile,LineNumberTable
-keepattributes Signature
-dontwarn com.jcraft.jzlib.**
-keep class com.jcraft.jzlib.** { *;}
-dontwarn sun.misc.**
-keep class sun.misc.** { *;}
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.** { *;}
-dontwarn sun.security.**
-keep class sun.security.** { *; }
-dontwarn com.google.**
-keep class com.google.** { *;}
-dontwarn com.avos.**
-keep class com.avos.** { *;}
-keep public class android.net.http.SslError
-keep public class android.webkit.WebViewClient
-dontwarn android.webkit.WebView
-dontwarn android.net.http.SslEr
-dontwarn android.webkit.WebViewClient
-dontwarn android.support.**
-dontwarn org.apache.**
-keep class org.apache.** { *;}
-dontwarn org.jivesoftware.smack.**
-keep class org.jivesoftware.smack.** { *;}
-dontwarn com.loopj.**
-keep class com.loopj.** { *;}
-dontwarn org.xbill.**
-keep class org.xbill.** { *;}
-keepattributes *Annotation*
# Gson
-keep class com.example.testing.retrofitdemo.bean.**{*;} # 自定義數據模型的bean目錄
#gson
#如果用用到Gson解析包的,直接添加下面這幾行就能成功混淆,不然會報錯。
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
# Application classes that will be serialized/deserialized over Gson
##---------------End: proguard configuration for Gson ----------
#基礎混淆添加配置
-keepclassmembers class **.R$* {
public static <fields>;
public static final int *;
}
-keepclassmembers class * extends android.app.Activity { # 保持自定義控件類不被混淆
public void *(android.view.View);
}
Ps: 這個也是我找的其實蠻全的,基本上常用的像:Gosn fastJson、Okhttp,以及一些初始化配置這裏都用。
但是需要注意的是:
關於實體類和一些自己常用的混淆命令
我們知道實體類是不能混淆的,並且每個項目的實體類都不一樣的,比如:你的實體類完整包名字:
com.xxx.xxx.bean
-keep class com.xxx.xxx.bean.**{*;}
表示當前路徑下全部文件都保持不被混淆
還有一個常用命令是:
-dontwarn
很多時候你會發現有些不能混淆的類你加了keep配置但是打包還是報錯,編譯不通過,這個時候你不妨用上這個命令比如:
-keep class com.jianke.ui.{*;}
-dontwarn com.jianke.ui.
這個表示不對當前包名下類警告,讓編譯通過
還有一些
-libraryjars class_path 不混淆指定的jar庫(android 項目中一般不混淆引入的第三方類庫)
等,具體可以看:
最全面的混淆規則