Android 代码混淆 包名被混淆 主工程二次混淆 一站解决你的混淆

代码混淆

(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码,也可以用于程序编译而成的中间代码。执行代码混淆的程序被称作代码混淆器。已经存在许多种功能各异的代码混淆器。

将代码中的各种元素,如变量,函数,类的名字改写成无意义的名字。比如改写成单个字母,或是简短的无意义字母组合,甚至改写成“__”这样的符号,使得阅读的人无法根据名字猜测其用途。重写代码中的部分逻辑,将其变成功能上等价,但是更难理解的形式。比如将for循环改写成while循环,将循环改写成递归,精简中间变量,等等。打乱代码的格式。比如删除空格,将多行代码挤到一行中,或者将一行代码断成多行等等。

代码混淆器也会带来一些问题。主要的问题包括:

被混淆的代码难于理解,因此调试以及除错也变得困难起来。开发人员通常需要保留原始的未混淆的代码用于调试。对于支持反射的语言,代码混淆有可能与反射发生冲突。代码混淆并不能真正阻止反向工程,只能增大其难度。因此,对于对安全性要求很高的场合,仅仅使用代码混淆并不能保证源代码的安全。

 Android混淆:常见的不参与

1.系统文件不参与混淆

2.反射不参与混淆

3.注解不参与混淆

4.EventBus不参与混淆

5.官方包下的类不参与混淆

常见不参与混淆需要keep下来的:

-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-ignorewarnings                     # 忽略警告,避免打包时某些警告出现
-optimizationpasses 5               # 指定代码的压缩级别
-dontusemixedcaseclassnames         # 是否使用大小写混合
-dontskipnonpubliclibraryclasses    # 是否混淆第三方jar
-dontpreverify                      # 混淆时是否做预校验
-verbose                            # 混淆时是否记录日志
-dontpreverify                      # 不进行预校验,预校验是作用在Java平台上的,Android平台上不需要这项功能,去掉之后还可以加快混淆速度
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*    # 混淆时所采用的算法

# 保留注解参数
-keepattributes *Annotation*
# 保留了继承自Activity、Application这些类的子类
# 因为这些子类有可能被外部调用
# 比如第一行就保证了所有Activity的子类不要被混淆
-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 * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
-keep public class * extends android.support.v4.**

#
# 枚举类不能被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
#
# 保留自定义控件(继承自View)不能被混淆
-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*(***);
    *** get* ();
}
#
# 保留Serializable 序列化的类不被混淆
-keep class * implements java.io.Serializable{
    *;
}

# 保留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();
}

# 对于带有回调函数onXXEvent的,不能混淆
-keepclassmembers class * {
    void *(**On*Event);
}
#
# 保留native方法的类名和方法名
-keepclasseswithmembernames class * {
    native <methods>;
}
#资源不混淆
-keep class **.R$* {*;}

2.针对包下所有的类不参与混淆:

keeppackagenames packagename

还有一种就是keep报下所有的类

-keep class com.test.action.entity.**{*;}

3.如果我们需要把我们的fragment,Activity提供给其他模块使用,需要不混淆fragment,Activity类名或者里面的某一个方法

如果我们只需要keep这个类名:-keep class com.test.fragment.TestFragment{*};

如果需要方法方法,把这个方法放进去即可。注意:方法的参数类型需要指定类的绝对className,不需要指定定义的参数

-keep class com.test.fragment.TestFragment{

public static void getInstance();

public void log(java.lang.String);

public void onEvent(com.test.User);

};

4.EventBus

 因为eventBus是通过注册类,在类中进行查找的。有人发现,我们在开发过程中,EventBus发送,代码混淆以后,接收不到,原因是因为onEvent(com.test.Entity)接收类被混淆了,在EventBus代码内部fork不到这个方法以及方法的参数匹配不上

所以要-keep class com.action.fragment.TestFragmrent{

public viod onEvent(com.test.entity.Entity);//参数指定参数classPath,后面不需要指定变量,正常as会关联到这个类的

}

-keep class com.action.fragment.TestActivity{

public viod onEvent(com.test.entity.Entity);//参数指定参数classPath,后面不需要指定变量,正常as会关联到这个类的

}

同样,这个参数也需要keep;

最好把Gson解析的类,或者eventBus,以及需要反射的类放到指定包下,这样只需要keep这个包以及下面所有的类即可。防止丢失

5.aar被主工程二次混淆

在选择混淆压缩的时候,不同的压缩算法会出现不同的混淆效果。R8开启的时候,混淆会被二次混淆,以至于连包名都会被混淆。

5.1包名混淆

 关闭R8

5.2 二次混淆

在主工程混淆文件需要keep一下aar或者其他module模块的包名,前提是所有的包都是以报名为前缀的,说检点的,就是你后来创建的包不要在模块报名外。

如果你的报名是:com.org.wiik.action

那么你所有新建的包都是在这个包名下,com.org.wiik.action.entity(package=entity)

这个包你如果已经混淆过了,只要在主工程

-keep class package.**{*;}

-keep class com.org.wiik.action.**{*}

这样就不会对aar进行二次混淆

6.资源被混淆报错:

Andorid NoSuchFieldError: No static field D of type I in class Lx/x/x/R$layout

只需要在混淆文件新增一下即可:

# 保留R下面的资源

-keep class **.R$* {*;}

#不混淆资源类下static的

-keepclassmembers class **.R$* {
public static <fields>;
}

备注:小黑板Gson.EventBus,anmation,View,有问题。找不到,需要多注意这些地方

在开发过程中,我们在debug模式下,可以先不需要开启混淆,因为混淆确实特别耗时,在转测的时候和上线的时候开启,方便验证。

猜你喜欢

转载自blog.csdn.net/qq36246172/article/details/115591096
今日推荐