本篇文章:自己在混淆的时候整理出比较全面的混淆方法,比较实用,自己走过的坑,淌出来的路。请大家不要再走回头路,可能只要我们代码加混淆,一点不对就会导致项目运行崩溃等后果,有许多人发现没有打包运行好好地,打包完成以后而又不不可以了,导致了许多困惑,本片文章来问大家解决困惑,希望对大家有帮助。
Android混淆最佳实践
1. 混淆配置
因为开启混淆会使编译时间变长,所以debug模式下不开启。我们需要做的是:
1.将release下minifyEnabled
的值改为true
,打开混淆;
2.加上shrinkResources true
,打开资源压缩。
3.buildConfigField
不显示log日志
4.signingConfig signingConfigs.config
配置签名文件文件
自定义混淆规则
自定义混淆方案适用于大部分的项目
android{ buildTypes { release { buildConfigField "boolean", "LOG_DEBUG", "false" //不显示log minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.config } } }
or
buildTypes { debug { minifyEnabled false // 混淆 zipAlignEnabled true // Zipalign优化 shrinkResources true // 移除无用的resource文件 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 加载默认混淆配置文件 signingConfig signingConfigs.debug // 签名 } release { minifyEnabled true // 混淆 zipAlignEnabled true // Zipalign优化 shrinkResources true // 移除无用的resource文件 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 加载默认混淆配置文件 signingConfig signingConfigs.relealse // 签名 } }
2. 混淆规则
混淆会用无意义的短变量去重命名类、变量、方法,但是对于外部的一些引用是通过名字找到对应的方法和类。混淆过后通过原来的名字去找混淆后的名字,是找不到对应方法和类,就会出异常报错。所以有些情况是不能进行混淆的。
- 自定义控件不进行混淆
- 枚举类不被混淆
- 反射类不进行混淆
- 实体类不被混淆
- JS调用的Java方法
- 四大组件不进行混淆
- JNI中调用类不进行混淆
- Layout布局使用的View构造函数、android:onClick等
- Parcelable 的子类和 Creator 静态成员变量不混淆
- 第三方开源库或者引用其他第三方的SDK包不进行混淆
3. 混淆模板
1)基本指令
# 设置混淆的压缩比率 0 ~ 7 -optimizationpasses 5 # 混淆时不使用大小写混合,混淆后的类名为小写 -dontusemixedcaseclassnames # 指定不去忽略非公共库的类 -dontskipnonpubliclibraryclasses # 指定不去忽略非公共库的成员 -dontskipnonpubliclibraryclassmembers # 混淆时不做预校验 -dontpreverify # 混淆时不记录日志 -verbose # 忽略警告 -ignorewarning # 代码优化 -dontshrink # 不优化输入的类文件 -dontoptimize # 保留注解不混淆 -keepattributes *Annotation*,InnerClasses # 避免混淆泛型 -keepattributes Signature # 保留代码行号,方便异常信息的追踪 -keepattributes SourceFile,LineNumberTable # 混淆采用的算法 -optimizations !code/simplification/cast,!field/*,!class/merging/* # dump.txt文件列出apk包内所有class的内部结构 -dump class_files.txt # seeds.txt文件列出未混淆的类和成员 -printseeds seeds.txt # usage.txt文件列出从apk中删除的代码 -printusage unused.txt # mapping.txt文件列出混淆前后的映射 -printmapping mapping.txt
2)不需混淆的Android类
-keep public class * extends android.app.Fragment -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.preference.Preference -keep public class * extends android.content.ContentProvider -keep public class * extends android.support.v4.** -keep public class * extends android.support.annotation.** -keep public class * extends android.support.v7.** -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.** {*;}
3)support-v4包
-dontwarn android.support.v4.** -keep class android.support.v4.app.** { *; } -keep interface android.support.v4.app.** { *; } -keep class android.support.v4.** { *; }
4)support-v7包
-dontwarn android.support.v7.** -keep class android.support.v7.internal.** { *; } -keep interface android.support.v7.internal.** { *; } -keep class android.support.v7.** { *; }
5)support design
-dontwarn android.support.design.** -keep class android.support.design.** { *; } -keep interface android.support.design.** { *; } -keep public class android.support.design.R$* { *; }
6)避免混淆自定义控件类的 get/set 方法和构造函数
-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); }
7)关闭 Log日志
-assumenosideeffects class android.util.Log { public static boolean isLoggable(java.lang.String, int); public static int v(...); public static int i(...); public static int w(...); public static int d(...); public static int e(...); }
-dontoptimize
不要配置,不然将会关闭优化,导致日志语句不会被优化掉。
8)避免资源混淆
-keep class **.R$* {*;}
9)避免layout中onclick方法(android:onclick="onClick")混淆
-keepclassmembers class * extends android.app.Activity{ public void *(android.view.View); }
10)避免回调函数 onXXEvent 混淆
-keepclassmembers class * { void *(*Event); }
11)避免混淆枚举类
-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }
12)Natvie 方法不混淆
-keepclasseswithmembernames class * { native <methods>; }
13)避免Parcelable混淆
-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; }
14)避免Serializable接口的子类中指定的某些成员变量和方法混淆
-keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; !static !transient <fields>; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); }
15)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); }
16)ButterKnife混淆配置
-keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; } -keepclasseswithmembernames class * { @butterknife.* <fields>; } -keepclasseswithmembernames class * { @butterknife.* <methods>; }
17)OkHttp3混淆配置
-dontwarn com.squareup.okhttp3.** -keep class com.squareup.okhttp3.** { *;} -dontwarn okio.**
18)Retrofit2混淆配置
-dontwarn retrofit2.** -keep class retrofit2.** { *; } -keepattributes Signature -keepattributes Exceptions
19)RxJava、RxAndroid混淆配置
-dontwarn sun.misc.** -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { long producerIndex; long consumerIndex; } -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { rx.internal.util.atomic.LinkedQueueNode producerNode; } -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef { rx.internal.util.atomic.LinkedQueueNode consumerNode; }
20)Glide混淆配置
- Glide 3
-keep public class * implements com.bumptech.glide.module.GlideModule -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; }
- Glide 4
-keep public class * implements com.bumptech.glide.module.AppGlideModule -keep public class * implements com.bumptech.glide.module.LibraryGlideModule -keep public enum com.bumptech.glide.load.ImageHeaderParser$** { **[] $VALUES; public *; }
21)Picasso混淆配置
-keep class com.parse.*{ *; } -dontwarn com.parse.** -dontwarn com.squareup.picasso.** -keepclasseswithmembernames class * { native <methods>; }
22)Fresco混淆配置
# Keep our interfaces so they can be used by other ProGuard rules. # See http://sourceforge.net/p/proguard/bugs/466/ -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip -keep,allowobfuscation @interface com.facebook.soloader.DoNotOptimize # Do not strip any method/class that is annotated with @DoNotStrip -keep @com.facebook.common.internal.DoNotStrip class * -keepclassmembers class * { @com.facebook.common.internal.DoNotStrip *; } # Do not strip any method/class that is annotated with @DoNotOptimize -keep @com.facebook.soloader.DoNotOptimize class * -keepclassmembers class * { @com.facebook.soloader.DoNotOptimize *; } # Keep native methods -keepclassmembers class * { native <methods>; } -dontwarn okio.** -dontwarn com.squareup.okhttp.** -dontwarn okhttp3.** -dontwarn javax.annotation.** -dontwarn com.android.volley.toolbox.** -dontwarn com.facebook.infer.**
23)Fastjson混淆配置
-dontwarn com.alibaba.fastjson.** -keep class com.alibaba.fastjson.**{*; }
24)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.** { *; }
25)Banner混淆配置
-keep class com.youth.banner.** { *; }
26)GreenDao混淆配置
- GreenDAO 2:
-keep class de.greenrobot.dao.** {*;} -keepclassmembers class * extends de.greenrobot.dao.AbstractDao { public static Java.lang.String TABLENAME; } -keep class **$Properties
- GreenDAO 3:
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao { public static java.lang.String TABLENAME; } -keep class **$Properties # If you do not use SQLCipher: -dontwarn org.greenrobot.greendao.database.** # If you do not use Rx: -dontwarn rx.**
27)百度定位混淆配置
-keep class vi.com.gdi.** { *; } -keep public class com.baidu.** {*;} -keep public class com.mobclick.** {*;} -dontwarn com.baidu.mapapi.utils.* -dontwarn com.baidu.platform.comapi.b.* -dontwarn com.baidu.platform.comapi.map.*
28)百度地图混淆配置
-keep class com.baidu.** {*;} -keep class vi.com.** {*;} -dontwarn com.baidu.**
29)高徳地图混淆配置
-dontwarn com.amap.api.** -dontwarn com.a.a.** -dontwarn com.autonavi.** -keep class com.amap.api.** {*;} -keep class com.autonavi.** {*;} -keep class com.a.a.** {*;}
30)Bugly混淆配置
-dontwarn com.tencent.bugly.** -keep public class com.tencent.bugly.**{*;}
31)EventBus混淆配置
- EventBus 2:
-keepclassmembers class ** { public void onEvent*(***); } # Only required if you use AsyncExecutor -keepclassmembers class * extends de.greenrobot.event.util.ThrowableFailureEvent { <init>(java.lang.Throwable); }
- EventBus 3:
-keepattributes *Annotation* -keepclassmembers class ** {
32)友盟分享混淆配置
-dontshrink -dontoptimize -dontwarn com.google.android.maps.** -dontwarn android.webkit.WebView -dontwarn com.umeng.** -dontwarn com.tencent.weibo.sdk.** -dontwarn com.facebook.** -keep public class javax.** -keep public class android.webkit.** -dontwarn android.support.v4.** -keep enum com.facebook.** -keepattributes Exceptions,InnerClasses,Signature -keepattributes *Annotation* -keepattributes SourceFile,LineNumberTable -keep public interface com.facebook.** -keep public interface com.tencent.** -keep public interface com.umeng.socialize.** -keep public interface com.umeng.socialize.sensor.** -keep public interface com.umeng.scrshot.** -keep public class com.umeng.socialize.* {*;} -keep class com.facebook.** -keep class com.facebook.** { *; } -keep class com.umeng.scrshot.** -keep public class com.tencent.** {*;} -keep class com.umeng.socialize.sensor.** -keep class com.umeng.socialize.handler.** -keep class com.umeng.socialize.handler.* -keep class com.umeng.weixin.handler.** -keep class com.umeng.weixin.handler.* -keep class com.umeng.qq.handler.** -keep class com.umeng.qq.handler.* -keep class UMMoreHandler{*;} -keep class com.tencent.mm.sdk.modelmsg.WXMediaMessage {*;} -keep class com.tencent.mm.sdk.modelmsg.** implements com.tencent.mm.sdk.modelmsg.WXMediaMessage$IMediaObject {*;} -keep class im.yixin.sdk.api.YXMessage {*