混淆

  • 混淆介绍: Android中的“混淆”可以分为两部分,一部分是 Java 代码的优化与混淆,依靠 proguard 混淆器来实现;另一部分是资源压缩,将移除项目及依赖的库中未被使用的资源。 官方混淆文档:https://www.guardsquare.com/en/proguard/manual/usage
混淆过程会有如下几个功能:

1.压缩。移除无效的类、类成员、方法、属性等;
2.优化。分析和优化方法的二进制代码;
根据proguard-android-optimize.txt中的描述,优化可能会造成一些潜在风险,
不能保证在所有版本的Dalvik上都正常运行。
3.混淆。把类名、属性名、方法名替换为简短且无意义的名称;
4.预校验。添加预校验信息。这个预校验是作用在Java平台上的,android平台上不需
要这项功能,去掉之后还可以加快混淆速度。

在 Android 项目中我们可以选择将“优化”和“预校验”关闭,
对应命令是-dontoptimize、-dontpreverify
(当然,默认的 proguard-android.txt 文件已包含这两条混淆命令,不需要开发者额外配置)。

1.混淆内容整理

对混淆内容整理分类,可分四个区:
1.基本指令区:限定混淆压缩比、混淆规则与混淆日志输出文件;建议全部保留。
2-3.默认保留区和定制区:这部分提出需要保留的内容,包括与清单文件相关的类和资源、
bean类、反射相关、系统接口、jni接口、枚举、泛型、自定义view的构造器、webview中js互调、v4与v7包、
fragment类、注解。
默认保留区建议全部保留,定制区需要根据项目配置。
4.第三方包混淆:项目中引用到的第三方包,需要根据项目配置。

1.1基本指令区

#---------------------------------基本指令区START----------------------------

# 代码混淆压缩比,在0和7之间,默认为5,一般不需要改
-optimizationpasses 5

# 混淆时不使用大小写混合,混淆后的类名为小写
-dontusemixedcaseclassnames

# 指定不去忽略非公共的库的类
-dontskipnonpubliclibraryclasses

# 指定不去忽略非公共的库的类的成员
-dontskipnonpubliclibraryclassmembers

# 优化时允许访问并修改有修饰符的类和类的成员
-allowaccessmodification

# 不做预校验,preverify是proguard的4个步骤之一
# Android不需要preverify,去掉这一步可加快混淆速度
-dontpreverify

#分析和优化方法的二进制代码;根据proguard-android-optimize.txt中的描述,
优化可能会造成一些潜在风险,不能保证在所有版本的Dalvik上都正常运行,建议关闭。
-dontoptimize

# 确定统一的混淆类的成员名称来增加混淆  
-useuniqueclassmembernames

# 忽略警告
-ignorewarnings

# 指定混淆时采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不改变
-optimizations !code/simplification/cast,!field/*,!class/merging/*

# 有了verbose这句话,混淆后就会生成映射文件
# 包含有类名->混淆后类名的映射关系
# 然后使用printmapping指定映射文件的名称
-verbose

# 记录生成的日志数据,gradle build时在本项目根目录输出##
# 抛出异常时保留代码行号,在异常分析中可以方便定位
-keepattributes SourceFile,LineNumberTable

# 混淆前后的映射
-printmapping mapping.txt

# 未混淆的类和成员
-printseeds seeds.txt

# 列出从 apk 中删除的代码
-printusage unused.txt

# apk 包内所有 class 的内部结构
-dump class_files.txt

#---------------------------------基本指令区END------------------------------

1.2默认保留区

#---------------------------------默认保留区START----------------------------
 
 # 避免混淆泛型
-keepattributes Signature

# 保留注解不被混淆
-keepattributes *Annotation*,InnerClasses
-keep class android.support.annotation.** { *; }
-keep interface android.support.annotation.** { *; }
 
 # 保留了继承自ActivityApplication等这些类的子类,因为这些子类,都有可能被外部调用
-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

#保留v4或者v7包
-dontwarn android.support.**
-keep class android.support.** {*; }

#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

# 枚举类不能被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#保持自定义控件类不被混淆
-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);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

# 保留Parcelable序列化的类不被混淆(Y)
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

# 保留Serializable序列化的类不被混淆
-keepnames class * implements java.io.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();
    public void set*(***);
    public *** get*();
}

# 对于R(资源)下的所有类及其方法,都不能被混淆
-keep class **.R$* {
 *;
}

#Fragment不需要在AndroidManifest.xml中注册,需要额外保护下
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment

# 保持测试相关的代码,不用输出测试类的通知和警告
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**

  

#---------------------------------默认保留区END----------------------------

1.3定制区(根据项目单独配置)

#--------------------------------定制区START---------------------------------
#----1.保留实体类----
-keep  class com.shanlin.shanxinbao.pager.fragment.requestData.** {*;}
-keep  class com.shanlin.shanxinbao.pager.fragment.responseData.** {*;}
-keep  class com.shanlin.shanxinbao.pager.activity.requestBean.** {*;}
-keep  class com.shanlin.shanxinbao.pager.activity.responseBean.** {*;}
-keep  class com.shanlinjinrong.shanxinbaosdk.common.net.BaseRequestData { *; }
-keep  class com.shanlinjinrong.shanxinbaosdk.common.net.BaseResponseData { *; }

#----2.与js互相调用的类---
#-keep class 你的类所在的包.** { *; }

#---3.反射相关的类和方法---
#-keep class 你的类所在的包.** { *; }

# ---4.对于带有回调函数onXXEvent---
#-keepclassmembers class * {
#    void *(**On*Event);
#}

#--------------------------------定制区END---------------------------------

1.3第三方依赖区(根据项目单独配置)

#-------------------------第三方包START------------------------------------
<例>:

#---OkHttp3---
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn com.squareup.okhttp.**

#---Retrofit2---
-dontnote retrofit2.Platform
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
-dontwarn retrofit2.Platform$Java8
-keepattributes Signature
-keepattributes Exceptions

#---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;
}

#---Glide---
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep class com.bumptech.glide.** { *; }
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
    **[] $VALUES;
    public *;
}

#-------------------------------第三方包END----------------------------------

2.混淆命令

2.1. 常见混淆命令:

这里罗列了项目中需要的命令,如需了解更多命令,请查阅 官网

命令 用途
-dontoptimize 关闭优化,优化可能会造成一些潜在风险,建议关闭
-optimizationpasses 代码混淆压缩比,在0和7之间,默认为5,一般不需要改
-dontusemixedcaseclassnames 混淆时不使用大小写混合,混淆后的类名为小写
-dontskipnonpubliclibraryclasses 指定不去忽略非公共的库的类
-dontpreverify 不做预校验,Android不需要,可加快混淆速度
-dontwarn 忽略警告
-verbose 混淆后就会生成映射文件
-optimizations 指定混淆时采用的算法
-keep 防止类和成员被移除或者被重命名
-keepnames 防止类和成员被重命名
-keepclassmembers 防止成员被移除或者被重命名
-keepclassmembernames 防止成员被重命名
-keepclasseswithmembers 防止拥有该成员的类和成员被移除或者被重命名
-keepclasseswithmembernames 防止拥有该成员的类和成员被重命名
-dontshrink 不压缩输入的类文件
-keepclasseswithmembernames 防止拥有该成员的类和成员被重命名
-useuniqueclassmembernames 确定统一的混淆类的成员名称来增加混淆

2.2 保持元素不参与混淆的规则

形如:

[保持命令] [类] {
    [成员] 
}

“类”代表类相关的限定条件,它将最终定位到某些符合该限定条件的类。 它的内容可以使用:

1. 具体的类
2. 通配符*,匹配任意长度字符,但不含包名分隔符(.)
3. 通配符**,匹配任意长度字符,并且包含包名分隔符(.)
4. extends,即可以指定类的基类
5. implement,匹配实现了某接口的类
6. $,内部类
7. 类的访问修饰符(publicprotectedprivate),不指定则表示任意修饰符

“成员”代表类成员相关的限定条件,它将最终定位到某些符合该限定条件的类成员。 它的内容可以使用:

1. <init> 匹配所有构造器
2. <fields> 匹配所有域
3. <methods> 匹配所有方法
    <例>:假如需要将name.huihui.test包下所有继承Activity的public类及其构造函数都保持住,可以这样写:
    -keep public class name.huihui.test.** extends Android.app.Activity {
        <init>
    }
4. 成员匹配:
    a.通配符*,匹配任意长度字符,但不含包名分隔符(.)
    b.通配符**,匹配任意长度字符,并且包含包名分隔符(.)
    c.通配符...,匹配任意参数类型
    <例>:void test(…)能匹配任意 void test(String a) 或者是 void test(int a, String b) 这些方法。
    d. 成员的访问修饰符(publicprotectedprivate),不指定则表示任意修饰符
2.3. 常用的自定义混淆规则
  • 不混淆某个类
-keep public class name.huihui.example.Test { *; }
  • 不混淆某个包所有的类
-keep class name.huihui.test.** { *; }
  • 不混淆某个类的子类
-keep public class * extends name.huihui.example.Test { *; }
  • 不混淆所有类名中包含了“model”的类及其成员
-keep public class **.*model*.** {*;}
  • 不混淆某个接口的实现
-keep class * implements name.huihui.example.TestInterface { *; }
  • 不混淆某个类的构造方法
-keepclassmembers class name.huihui.example.Test { 
  public <init>(); 
}
  • 不混淆某个类的特定的方法
-keepclassmembers class name.huihui.example.Test { 
  public void test(java.lang.String); 
}
  • 不混淆某个类的内部类
-keep class name.huihui.example.Test$* {
      *;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值