Apk文件被反編譯出來能被獲取到里面的代碼。對于這種情況捂齐,我們可以對項目代碼進行混淆蛮放,隨機生成難理解的類名,方法名奠宜,讓代碼難以閱讀包颁,加大功能被盜取的難度⊙拐妫混淆可以起到壓縮Apk娩嚼,混淆文件,預檢滴肿,優(yōu)化的作用岳悟。
1. 使用方式,在gradle文件中設置minifyEnabled為true即可開啟混淆
buildTypes {
release {
minifyEnabled ture //是否開啟代碼混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
混淆內容在proguard-android.txt或者proguard-rules.pro文件中寫泼差。
2. 混淆設置參數(shù)
-optimizationpasses 4 代碼混淆的壓縮比例贵少,值介于0-7
-dontusemixedcaseclassnames 混淆后類型都為小寫
-dontskipnonpubliclibraryclasses 不去忽略非公共的庫類
-dontoptimize 不優(yōu)化輸入的類文件
-dontpreverify 不做預校驗的操作
-ignorewarnings 忽略警告
-verbose 混淆時是否記錄日志
-keepattributes Annotation 保護注解
-printmapping proguardMapping.txt 生成原類名和混淆后的類名的映射文件mapping文件
-optimizations !code/simplification/cast,!field/,!class/merging/ 指定混淆是采用的算法
3. 保持不被混淆的設置
保持某個包下所有類不混淆
-keep class 你的實體類所在的包.** { *; }
四大組件、View體系等不混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Fragment
-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.preference.Preference
-keep public class * extends android.view.View
-keep class android.support.** {*;}
-keep public class * extends android.support.v4.**
-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);
}
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
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();
}
保持枚舉enum類不被混淆
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
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);
}
support design
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }
然后就是項目中使用到的第三方包不混淆拴驮,下面有示例春瞬。
4. 完整混淆示例:
#---------------------------------基本指令區(qū)-----------------------
-optimizationpasses 5 #指定代碼的壓縮級別
-dontpreverify #預校驗
-verbose #指定日志級別
-dontskipnonpubliclibraryclassmembers
-dontusemixedcaseclassnames #包名不混合大小寫
-ignorewarnings #忽略警告
-printmapping proguardMapping.txt #生成原類名和混淆后的類名的映射文件
-optimizations !code/simplification/cast,!field/*,!class/merging/* #混淆時所采用的算法
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
#---------------------------------默認保留區(qū)------------------------
#四大組件柴信、View體系等
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Fragment
-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.preference.Preference
-keep public class * extends android.view.View
-keep class android.support.** {*;}
-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);
}
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
#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();
}
-keep class **.R$* {
*;
}
-keepclassmembers class * {
void *(*Event);
}
#enum
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclassmembers class * {
public <init> (org.json.JSONObject);
}
-keepclasseswithmembernames class * {
native <methods>;
}
#Parcelable
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#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);
}
# support design
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }
#---------------------------------第三方包示例-------------------------
#okhttp3.x
-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-dontwarn okio.**
-dontwarn com.squareup.okhttp.**
-keep class com.squareup.okhttp.{*;}
-dontwarn javax.annotation.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.ConscryptPlatform
#retrofit
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-dontwarn okio.**
#Rxjava RxAndroid
-dontwarn rx.*
-dontwarn sun.misc.**
#Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
#Gson
-keep class com.google.gson.** {*;}
-keep class com.google.**{*;}
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }
#Lambda表達式
-keep class java.lang.invoke.** {*;}
-dontwarn java.lang.invoke.**
#高徳地圖
#3D 地圖
-keepclass com.amap.api.mapcore.**{*;}
-keepclass com.amap.api.maps.**{*;}
-keepclass com.autonavi.amap.mapcore.*{*;}
#定位
-keepclass com.amap.api.location.**{*;}
-keepclass com.loc.**{*;}
-keepclass com.amap.api.fence.**{*;}
-keepclass com.autonavi.aps.amapapi.model.**{*;}
# 搜索
-keepclass com.amap.api.services.**{*;}
# 2D地圖
-keepclass com.amap.api.maps2d.**{*;}
-keepclass com.amap.api.mapcore2d.**{*;}
# 導航
-keepclass com.amap.api.navi.**{*;}
-keepclass com.autonavi.**{*;}
#ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
#eventbus 3.0
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
#ARouter組件化
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
自己試著用一個簡單的項目加入混淆套啤,打個包試試效果吧。
混淆sdk和避免混淆部分類實戰(zhàn):
1.在proguard-rules.pro文件下配置混淆參數(shù)和-keep的類或者包:
# 混淆時所采用的算法
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
#指定代碼的壓縮級別
-optimizationpasses 5
-allowaccessmodification
# 優(yōu)化 不優(yōu)化輸入的類文件
-dontoptimize
# 預校驗
-dontpreverify
# 包名不混合大小寫
-dontusemixedcaseclassnames
# 混淆時是否記錄日志
-verbose
# 保護注解
-keepattributes *Annotation*
# 忽略警告
-ignorewarnings
-printconfiguration build/intermediates/proguard-files/full-r8-config.txt
# 保持哪些類不被混淆
#保持sdk中需要暴露功能的包下所有類不被混淆
-keep class com.libo.networkmonitor.api.**{*;}
-keep class com.libo.networkmonitor.impl.NetWorkListener
2.設置release模式下開啟混淆:
buildTypes {
release {
minifyEnabled true
proguardFiles 'proguard-rules.pro'
}
debug {
minifyEnabled false
proguardFiles 'proguard-rules.pro'
}
}
3.打出sdk的aar包随常,并進行引用查看混淆情況:
可以看到潜沦,打出來的aar包,keep的類可以看到原寫法绪氛,因為上面NetworkMonitor的類避免了混淆可以看得到唆鸡,其余被混淆的類變成了看不出來的字母。
Mapping文件使用
列出了原始的類枣察,方法和字段名與混淆后代碼間的映射争占。這個文件很重要,當你從release版本中收到一個bug報告時序目,混淆后的文件看不出問題臂痕,可以用它來翻譯被混淆的代碼。
mapping目錄在 \app\build\outputs\mapping\release
示例:
或者將mapping文件上傳到監(jiān)測平臺猿涨,報出問題就能直接閱讀了握童。