混淆是常用的减小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}