混淆是常用的减小app大小,增加app安全性的方法。
作用
代码混淆由ProGuard提供支持,ProGuard会检测和移除封装应用中未使用的类、字段、方法和属性,包括自带代码库中的未使用项(这使其成为以变通方式解决64k引用限制的有用工具)。ProGuard还可优化字节码,移除未使用的代码指令,以及用短名称混淆其余的类、字段和方法。混淆过的代码可令您的APK难以被逆向工程,这在应用使用许可验证等安全敏感性功能时特别有用。
以上为Android官网原文描述,其主要作用主要有那么几点:
- 减少方法数
- 增加反编译的难度
- app瘦身
一言不合上实例
以下为收集整理的混淆配置,复制到项目就可使用
- 通用配置
#开启即可关闭混淆 #-dontobfuscate #---------------Begin: proguard configuration common for all Android apps ----------# #指定代码的压缩级别 -optimizationpasses 5 #包名不混合大小写 -dontusemixedcaseclassnames #不去忽略非公共的库类 -dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclassmembers #优化 不优化输入的类文件 -dontoptimize #预校验 -dontpreverify #混淆时是否记录日志 -verbose # 混淆时所采用的算法 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* #-------------start:记录生成的日志数据,gradle build时在本项目根目录输出-------------# #apk 包内所有 class 的内部结构 -dump proguard/class_files.txt #未混淆的类和成员 -printseeds proguard/seeds.txt #列出从 apk 中删除的代码 -printusage proguard/unused.txt #混淆前后的映射 -printmapping proguard/mapping.txt #-------------End:记录生成的日志数据,gradle build时在本项目根目录输出-------------# #避免混淆泛型 如果混淆报错建议关掉 #-keepattributes Signature #保护注解 -keepattributes *Annotation* # 保持哪些类不被混淆 -keep public class * extends android.support.v4.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.content.ContentProvider -keep public class * extends android.app.backup.BackupAgentHelper -keep public class * extends android.preference.Preference -keep public class com.android.vending.licensing.ILicensingService -dontnote com.android.vending.licensing.ILicensingService #如果有引用v4包可以添加下面这行 #-keep public class * extends android.support.v4.app.Fragment #忽略警告 -ignorewarning #如果引用了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); } -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>; } -keep class **.R { *; } -keep class **.R$* { *; } #移除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(...); #} -keepclassmembers class * { @android.webkit.JavascriptInterface <methods>; } -keep class * extends java.util.ListResourceBundle { protected Object[][] getContents(); }
- ReactNative混淆配置
#------------------------Start: React Native------------------------# # 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.proguard.annotations.DoNotStrip -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip # Do not strip any method/class that is annotated with @DoNotStrip -keep @com.facebook.proguard.annotations.DoNotStrip class * -keep @com.facebook.common.internal.DoNotStrip class * -keepclassmembers class * { @com.facebook.proguard.annotations.DoNotStrip *; @com.facebook.common.internal.DoNotStrip *; } -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { void set*(***); *** get*(); } -keep class com.facebook.react.cxxbridge.ModuleRegistryHolder { *; } -keep class com.facebook.react.cxxbridge.CatalystInstanceImpl { *; } -keep class com.facebook.react.cxxbridge.JavaScriptExecutor { *; } -keep class com.facebook.react.bridge.queue.NativeRunnable { *; } -keep class com.facebook.react.bridge.ExecutorToken { *; } -keep class com.facebook.react.bridge.ReadableType { *; } -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } -keep class * extends com.facebook.react.bridge.NativeModule { *; } -keepclassmembers,includedescriptorclasses class * { native <methods>; } -keepclassmembers class * { @com.facebook.react.uimanager.UIProp <fields>; } -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp <methods>; } -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup <methods>; } -dontwarn com.facebook.react.** # stetho -dontwarn com.facebook.stetho.** -keep class android.text.StaticLayout #------------------------End: React Native------------------------#
- Gson
-keepattributes Signature -keepattributes *Annotation* -keep class sun.misc.Unsafe { *; } # Application classes that will be serialized/deserialized over Gson # 下面替换成自己的实体类 -keep class com.example.bean.** { *; }
- Butter Knife
-keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; } -keepclasseswithmembernames class * { @butterknife.* <fields>; } -keepclasseswithmembernames class * { @butterknife.* <methods>; }
- Okio
-dontwarn com.squareup.** -dontwarn okio.** -keep public class org.codehaus.* { *; } -keep public class java.nio.* { *; }
- OkHttp3
-dontwarn com.squareup.okhttp3.** -keep class com.squareup.okhttp3.** { *;} -dontwarn okio.**
- Retrofit
-dontwarn retrofit2.** -keep class retrofit2.** { *; } -keepattributes Signature -keepattributes Exceptions
- Ormlite
-keepattributes *DatabaseField* -keepattributes *DatabaseTable* -keepattributes *SerializedName* -keep class com.j256.** -keepclassmembers class com.j256.** { *; } -keep enum com.j256.** -keepclassmembers enum com.j256.** { *; } -keep interface com.j256.** -keepclassmembers interface com.j256.** { *; }
- 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; }
- AndroidEventBus
-keep class org.simple.** { *; } -keep interface org.simple.** { *; } -keepclassmembers class * { @org.simple.eventbus.Subscriber <methods>; }
- EventBus
-keepattributes *Annotation* -keepclassmembers class ** { @org.greenrobot.eventbus.Subscribe <methods>; } -keep enum org.greenrobot.eventbus.ThreadMode { *; }
- Glide
-keep public class * implements com.bumptech.glide.module.GlideModule -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; }
混淆语法解析
- 保留选项(配置不进行处理的内容)
# 保护指定的类文件和类的成员 -keep {modifier} {class_specification} # 保护指定类的成员,如果此类受到保护他们会保护的更好 -keepclassmembers {modifier} {class_specification} # 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。 -keepclasseswithmembers {class_specification} # 保护指定的类和类的成员的名称(如果他们不会压缩步骤中删除) -keepnames {class_specification} # 保护指定的类的成员的名称(如果他们不会压缩步骤中删除) -keepclassmembernames {class_specification} # 保护指定的类和类的成员的名称,如果所有指定的类成员出席(在压缩步骤之后) -keepclasseswithmembernames {class_specification} # 列出类和类的成员-keep选项的清单,标准输出到给定的文件 -printseeds {filename}
- 压缩
# 不压缩输入的类文件 -dontshrink # 打印为什么一个类或类的成员被保护,这对检查一个输出文件中的类的结果有帮助. -whyareyoukeeping {class_specification} # 将被删除的元素输出到文件 -printusage {filename}
- 优化
# 不优化输入的类文件 -dontoptimize # 优化时假设指定的方法,没有任何副作用 -assumenosideeffects {class_specification} # 优化时允许访问并修改有修饰符的类和类的成员 -allowaccessmodification
- 混淆
# 不混淆输入的类文件 -dontobfuscate # 使用给定文件中的关键字作为要混淆方法的名称 -obfuscationdictionary {filename} # 混淆时应用侵入式重载 -overloadaggressively # 确定统一的混淆类的成员名称来增加混淆 -useuniqueclassmembernames # 重新包装所有重命名的包并放在给定的单一包中 -flattenpackagehierarchy {package_name} # 重新包装所有重命名的类文件中放在给定的单一包中 -repackageclass {package_name} # 混淆时不会产生形形色色的类名 -dontusemixedcaseclassnames # 保护给定的可选属性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses. -keepattributes {attribute_name,...} # 设置源文件中给定的字符串常量 -renamesourcefileattribute {string}