Proguard混淆入门手册

代码混淆

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

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

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

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

Java是一种跨平台的、解释型语言,Java源代码编译成中间“字节码”存储于class文件中。由于跨平台的需要,Java字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成Java源代码。为了防止这种现象,我们可以使用Java混淆器对Java字节码进行混淆。

混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的情况下,即使被反编译,也将难以阅读。同时混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

混淆器的作用不仅仅是保护代码,它也有精简编译后程序大小的作用。由于以上介绍的缩短变量和函数名以及丢失部分信息的原因, 编译后jar文件体积大约能减少25% ,这对当前费用较贵的无线网络传输是有一定意义的。

此处转载于:https://baike.baidu.com/item/%E4%BB%A3%E7%A0%81%E6%B7%B7%E6%B7%86/1892288?fr=aladdin

ProGuard https://www.guardsquare.com/en/products/proguard/manual

proguard是最流行的java字节码优化器。 它使您的java和Android应用程序文件小到90%,执行速度提升20%。 proguard还通过混淆类、字段和方法的名称来增加逆向工程的难度。

ProGuard是Java class文件压缩器、优化器、混淆器和预校验器。压缩步骤检测并删除未使用的类、字段、方法和属性。优化步骤对方法的字节码进行了分析和优化。混淆步骤使用无意义的短名称重命名保留的类、字段和方法。这些步骤使代码文件更小,更高效,更难逆向。

最后的预校验步骤将预校验信息添加到classes中,这是Java Micro Edition和Java 6及更高版本所必需的,编译时可以把预校验信息添加到类文件中(StackMap 和 StackMapTable属性),从而加快类加载效率。
Android会把class编译成dex,并对dex文件进行校验,对class进行预校验是多余的。

这些步骤中的每一个都是可选的。例如,ProGuard还可以用于仅列出应用程序中的无作用代码,或者用于预校验class文件,以便在Java 6中有效使用。

ProGuard是一个压缩、优化和混淆Java字节码文件的免费的工具,它可以删除无用的类、字段、方法和属性。可以删除没用的注释,最大限度地优化字节码文件。它还可以使用简短的无意义的名称来重命名已经存在的类、字段、方法和属性。常常用于Android开发用于混淆最终的项目,增加项目被反编译的难度。

ProGuard执行流程

在这里插入图片描述
ProGuard首先读取输入的jar包(或aar、war、ear、zip、apk或目录),然后压缩、优化、混淆和预校验,您可以随意选择让ProGuard执行哪些优化步骤。ProGuard将处理的结果写入一个或多个jar(或aar、war、ear、zip、apk或目录)。输入可以包含资源文件,其名称和内容可以随意地更新以映射混淆后的class名称。

为了确定哪些代码必须保留,哪些代码可以丢弃或混淆,您必须指定一个或多个代码入口点。这些入口点通常是带有main方法、applet等的类。

压缩

默认开启

在压缩步骤,ProGuard递归地确定代码使用了哪些类和类成员,其他类和类成员都会被删除。

JAVA源代码(.java文件)通常被编译为字节码(.class文件)。而完整的程序或程序库通常被压缩和发布成Java文档(.jar文件)。字节码比 Java源文件更简洁,但是它仍然包含大量的无用代码,尤其它是一个程序库的时候。ProGuard的压缩程序操作能分析字节码,并删除无用的类、字段和方法。程序只保留功能上的等价,包括异常堆栈描述所需要的信息。

shrinkResources

shrinkResources true
没有引用到的图片资源会被压缩成1像素大小;
没有引用到的布局文件会被压缩成

<?xml version="1.0"encoding="utf-8"?>
<x/>

没有引用到的string不会被压缩,当然这是无所谓的,毕竟蚊子一点大,成不了气候,还有color也是

优化

默认开启

在优化步骤,ProGuard进一步优化代码。在其他优化中,可以将非入口点的类和方法变为私有、静态或final的,可以删除未使用的参数,并且可以内联某些方法,目的是为了提升代码执行效率。

ProGuard支持以下种类的优化:

除了在压缩操作删除的无用类,字段和方法外,ProGuard也能在字节码级提供性能优化,内部方法有:
常量表达式求值
删除不必要的字段存取
删除不必要的方法调用
删除不必要的分支
删除不必要的比较和instanceof验证
删除未使用的代码
删除只写字段
删除未使用的方法参数
像push/pop简化一样的各种各样的peephole优化
在可能的情况下为类添加static和final修饰符
在可能的情况下为方法添加private, static和final修饰符
在可能的情况下使get/set方法成为内联的
当接口只有一个实现类的时候,就取代它
选择性的删除日志代码

此处转载于:https://baike.baidu.com/item/ProGuard/5627019?fr=aladdin

混淆

默认开启

在混淆步骤,使用简短的无意义的名称来重命名已经存在的类、字段、方法和属性,ProGuard重命名不是入口点的类和类成员。在整个过程中,保留入口点确保它们仍然可以被原始名称访问。

预校验

这个预校验步骤是唯一不需要知道入口点的步骤。

最后的预校验步骤将预校验信息添加到classes中,这是Java Micro Edition和Java 6及更高版本所必需的,编译时可以把预校验信息添加到类文件中(StackMapStackMapTable属性),从而加快类加载效率。

Android会把class编译成dex,并对dex文件进行校验,对class进行预校验是多余的。

反射

反射给混消时代码的自动处理带来了特殊的问题。在ProGuard中,代码中动态创建或调用的类或类成员(即名称)也必须指定为入口点。例如,Class.forName()可以在运行时引用任何类。通常不可能知道哪些类必须保留,因为类名可能是从配置文件中读取的。因此,您必须在ProGuard配置中用-keep保留它们。

所幸,ProGuard已经为您检测并处理了以下情况:

Class.forName("SomeClass")
SomeClass.class
SomeClass.class.getField("someField")
SomeClass.class.getDeclaredField("someField")
SomeClass.class.getMethod("someMethod", null)
SomeClass.class.getMethod("someMethod", new Class[] { A.class,... })
SomeClass.class.getDeclaredMethod("someMethod", null)
SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class,... })
AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")

当你在java代码中调用以上反射代码时,混淆器会自动将你的类、方法、属性混淆,不会出现问题

在Android Studio中测试,建类如下:
在这里插入图片描述

package com.cy.utils;

public class MyClass {
    private String s;
    private void add(MyClass myClass){}
    private void add(){}
}

package com.cy.utils;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
public class Test {
    public static void getM() throws Exception {
       Class clazz= Class.forName("com.cy.utils.MyClass");
        Class clazz1 = MyClass.class;
        MyClass.class.getField("s");
        MyClass.class.getDeclaredField("s");
        MyClass.class.getMethod("add", null);
        MyClass.class.getMethod("add", new Class[]{MyClass.class });
        MyClass.class.getDeclaredMethod("add", null);
        MyClass.class.getDeclaredMethod("add", new Class[]{MyClass.class });
        AtomicIntegerFieldUpdater.newUpdater(MyClass.class, "s");
        AtomicLongFieldUpdater.newUpdater(MyClass.class, "s");
        AtomicReferenceFieldUpdater.newUpdater(MyClass.class, MyClass.class, "s");
    }
}

添加混淆配置:
在这里插入图片描述
配置:

-dontshrink

小编是在子模块里release的,所以要配置不压缩,不然release出来的jar里什么都没有,会被移除。

混淆结果如下:

package a.a.a;
public class b {
  public String a;
  private void a(b paramb) {}
  private void a() {}
}
package a.a.a;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
public class c {
  public static void a() {
    Class.forName("a.a.a.b");
    b.class.getField("a");
    b.class.getDeclaredField("a");
    b.class.getMethod("a", null);
    Class[] arrayOfClass;
    (arrayOfClass = new Class[1])[0] = b.class;
    b.class.getMethod("a", arrayOfClass);
    b.class.getDeclaredMethod("a", null);
    (arrayOfClass = new Class[1])[0] = b.class;
    b.class.getDeclaredMethod("a", arrayOfClass);
    AtomicIntegerFieldUpdater.newUpdater(b.class, "a");
    AtomicLongFieldUpdater.newUpdater(b.class, "a");
    AtomicReferenceFieldUpdater.newUpdater(b.class, b.class, "s");
  }
}

可以看到混淆结果相当满意,运行并不会出现毛病。

注意: 如果你做的是SDK,你的代码里用了反射,如果你要混淆,你需要保证别人使用你的SDK的时候,没有反射你SDK里的某些类,否则GG,当然一般不会出现这样的情况。

Android Studio混淆

Android Studio开启混淆贼容易,在对应模块的build.gradle下添加如下代码:

   buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

release 表示只有在release APK或者release 模块的时候,会执行混淆

minifyEnabled true表示开启混淆,false表示不混淆

proguard-rules.pro 是混淆文件

如图:
在这里插入图片描述
release APK的时候,并且全局启动了混淆,子模块libs下的aar里的class不会被混淆,子模块libs下的jar里的class会被混淆
release 模块的时候,无论是否开启混淆,该模块libs下的aar均不会被保留,开启混淆并且keep住libs下jar的的class,keep的class会被保留。
子模块需要配置consumerProguardFiles,才能控制对自身模块的混淆,否则会使用全局的混淆

如果在多个子模块的consumerProguardFiles中设置了相同语句,比如:-repackageclasses,会被最内层的子模块覆盖,例如app引用A模块,A模块引用B模块,将会使用B模块的配置。

用compileOnly添加的jar包,即使在混消时keep了,依然无法保留。

子模块依赖了其他子模块,release出来的aar/jar里没有其他子模块的class,并且自身引用其他子模块的class无论如何也不会被混淆。
如引用:

import com.utils.BitmapUtils ;
public class Test{
  private BitmapUtils bitmapUtils;
  private ImageLoader imageLoader;
}

BitmapUtils 来自其他子模块,那么混淆后结果:

import com.utils.BitmapUtils ;
public class Test{
  private BitmapUtils e;
  private a v;
}

com.utils.BitmapUtils无论如何也不会被混淆

子模块依赖了aar,用compileOnly依赖时,release该模块,aar里的内容不会添加进去(api、implementation依赖时,会被添加进去),并且无论如何都不会被混淆

子模块依赖了jar,用compileOnly依赖时,release该模块,jar里的内容不会添加进去(api、implementation依赖时,会被添加进去),会被混淆

多模块APP混淆

app模块用 proguardFiles

buildTypes {
        release {
            minifyEnabled rootProject.ext.minifyEnabled
            zipAlignEnabled rootProject.ext.zipAlignEnabled
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    '../zzz_proguard/base-proguard-rules.pro',
                    "../zzz_proguard/app-proguard-rules.pro"
            signingConfig signingConfigs.release
        }
    }

子模块用consumerProguardFiles

  buildTypes {
        release {
            minifyEnabled rootProject.ext.minifyEnabled
            zipAlignEnabled rootProject.ext.zipAlignEnabled
            consumerProguardFiles '../zzz_proguard/base-proguard-rules.pro',
                    "../zzz_proguard/http-proguard-rules.pro"

        }
    }

只混淆自身模块

proguardFiles

 buildTypes {
        release {
            minifyEnabled rootProject.ext.minifyEnabled
            zipAlignEnabled rootProject.ext.zipAlignEnabled
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                    '../zzz_proguard/base-proguard-rules.pro',
                    "../zzz_proguard/utils-proguard-rules.pro"
        }
    }

Github源码:
https://github.com/AnJiaoDe/MakeJar

混淆Jar包,首先得有一个普通的Jar包
死丢丢如何将多module生成一个Jar包?
在这里插入图片描述
目前小编掌握的比较简单方便的方法是:需要在所有module的build目录找到对应的class文件,然后合并
如各位有更好的方法,欢迎屏幕下方留言讨论,喜欢的朋友可以点击关注,了解更多
比如开发一个SDK,但是有多module依赖关系如下:
在这里插入图片描述
在这里插入图片描述
生成Jar包方式如下:
在app module下的build.gradle加入如下配置

def SDK_DEBUG_BASENAME = "makeJar-debug-" + new Date().format("yyyy-MM-dd");//未混淆的jar名字
def SDK_RELEASE_BASENAME = "makeJar-release-" + new Date().format("yyyy-MM-dd");//混淆后的jar名字
def SDK_OUTPATH = "libs/";//生成Jar的目录
//生成未混淆的Jar
task makeJar(type: Jar) {
    delete SDK_OUTPATH+SDK_DEBUG_BASENAME+'.jar'//删除原来的jar
    //包括子module额class文件
    from('../utils/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes')
    from('../http/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes')
    from('../router/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes')
    from('../amodule/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes')
    from('../manager/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes')
    from(project.zipTree('..\\router\\libs\\protobuf-lite-3.0.0.jar'))//合并其他Jar
//    //去掉不需要打包的目录和文件
    exclude('BuildConfig.class', 'R.class')
    //去掉R$开头的文件
    exclude { it.name.startsWith('R$'); }
    baseName = SDK_DEBUG_BASENAME
    destinationDir = file(SDK_OUTPATH)
}

操作方式如下:
在这里插入图片描述
混淆Jar包方式如下:
在app module下的build.gradle加入如下配置

//混淆Jar
task proguard(type: proguard.gradle.ProGuardTask) {
    delete SDK_OUTPATH+SDK_RELEASE_BASENAME+'.jar'//删除原来的jar
    configuration "${rootProject.rootDir}/proguard-rules.pro"//配置混淆文件
    injars SDK_OUTPATH+SDK_DEBUG_BASENAME+'.jar'//未混淆的Jar
    outjars SDK_OUTPATH+SDK_RELEASE_BASENAME+'.jar'//混淆后的Jar
}
proguard.dependsOn(makeJar)//必须添加此行,不然混淆失败

操作方式如下:
在这里插入图片描述
混淆文件的配置
在这里插入图片描述

混淆文件内容如下:

# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\AndroidSDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

#
#-------------------------------------------基本不用动区域----------------------------------------------
#
#
# -----------------------------基本 -----------------------------
#

# 指定代码的压缩级别 0 - 7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用。)
-optimizationpasses 5
# 混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名)
-dontusemixedcaseclassnames
# 指定不去忽略非公共的库类(不跳过library中的非public的类)
-dontskipnonpubliclibraryclasses
# 指定不去忽略包可见的库类的成员
-dontskipnonpubliclibraryclassmembers
#不进行优化,建议使用此选项,
-dontoptimize
 # 不进行预校验,Android不需要,可加快混淆速度。
-dontpreverify
# 屏蔽警告
-ignorewarnings
# 指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# 保护代码中的Annotation不被混淆
-keepattributes *Annotation*
# 避免混淆泛型, 这在JSON实体映射时非常重要
-keepattributes Signature
# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
 #优化时允许访问并修改有修饰符的类和类的成员,这可以提高优化步骤的结果。
# 比如,当内联一个公共的getter方法时,这也可能需要外地公共访问。
# 虽然java二进制规范不需要这个,要不然有的虚拟机处理这些代码会有问题。当有优化和使用-repackageclasses时才适用。
#指示语:不能用这个指令处理库中的代码,因为有的类和类成员没有设计成public ,而在api中可能变成public
-allowaccessmodification
#当有优化和使用-repackageclasses时才适用。
-repackageclasses ''
 # 混淆时记录日志(打印混淆的详细信息)
 # 这句话能够使我们的项目混淆后产生映射文件
 # 包含有类名->混淆后类名的映射关系
-verbose
#
##
## ----------------------------- 默认保留 -----------------------------
##
##----------------------------------------------------
## 保持哪些类不被混淆
#继承activity,application,service,broadcastReceiver,contentprovider....不进行混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.support.multidex.MultiDexApplication
-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 class android.support.** {*;}## 保留support下的所有类及其内部类

-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
#表示不混淆上面声明的类,最后这两个类我们基本也用不上,是接入Google原生的一些服务时使用的。
#----------------------------------------------------

# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**


#表示不混淆任何包含native方法的类的类名以及native方法名,这个和我们刚才验证的结果是一致
-keepclasseswithmembernames class * {
    native <methods>;
}


#这个主要是在layout 中写的onclick方法android:onclick="onClick",不进行混淆
#表示不混淆Activity中参数是View的方法,因为有这样一种用法,在XML中配置android:onClick=”buttonClick”属性,
#当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法,如果这个方法被混淆的话就找不到了
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}

#表示不混淆枚举中的values()和valueOf()方法,枚举我用的非常少,这个就不评论了
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

#表示不混淆任何一个View中的setXxx()和getXxx()方法,
#因为属性动画需要有相应的setter和getter的方法实现,混淆了就无法工作了。
-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实现类中的CREATOR字段,
#毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,不然整个Parcelable工作机制都会失败。
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
# 这指定了继承Serizalizable的类的如下成员不被移除混淆
-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();
}
# 保留R下面的资源
#-keep class **.R$* {
# *;
#}
#不混淆资源类下static的
-keepclassmembers class **.R$* {
    public static <fields>;
}

# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
    void *(**On*Listener);
}
#保持内部类能正常引用
-keepattributes Exceptions,InnerClasses

# 保留我们自定义控件(继承自View)不被混淆
-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);
}

#
#----------------------------- WebView(项目中没有可以忽略) -----------------------------
#
#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);
}
#在app中与HTML5的JavaScript的交互进行特殊处理
#我们需要确保这些js要调用的原生方法不能够被混淆,于是我们需要做如下处理:
-keepclassmembers class com.ljd.example.JSInterface {
    <methods>;
}

#
#---------------------------------实体类---------------------------------
#--------(实体Model不能混淆,否则找不到对应的属性获取不到值)-----
#
-dontwarn com.suchengkeji.android.confusiondemo.md.**
#对含有反射类的处理
-keep class com.suchengkeji.android.confusiondemo.md.** { *; }
#
# ----------------------------- 其他的 -----------------------------
#
# 删除代码中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(...);
}

# 保持测试相关的代码
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**


#
# ----------------------------- 第三方 -----------------------------
#
-dontwarn com.orhanobut.logger.**
-keep class com.orhanobut.logger.**{*;}
-keep interface com.orhanobut.logger.**{*;}

-dontwarn com.google.gson.**
-keep class com.google.gson.**{*;}
-keep interface com.google.gson.**{*;}

#   -------------------------------multidata sdk------------------------------------------------------
#不移除资源,必须写这行,不写,module的所有没有用到的类都会被移除
-dontshrink

#utils
-keepnames class com.cy.utils.**{
  protected <methods>;
  public <methods>;
}
#http
-keepnames class com.cy.http.StringCallbackImpl{
  protected <methods>;
  public <methods>;
}
-keepnames class com.cy.http.ProtobufCallbackImpl{
  protected <methods>;
  public <methods>;
}
-keepnames class com.cy.http.Imageloader{
  protected <methods>;
  public <methods>;
}
-keepnames class com.cy.http.HttpUtils{
  protected <methods>;
  public <methods>;
}
-keepnames class com.cy.http.FileCallbackImpl{
  protected <methods>;
  public <methods>;
}
-keepnames class com.cy.http.Callback{
  protected <methods>;
  public <methods>;
}
-keepnames class com.cy.http.BitmapCallbackImpl{
  protected <methods>;
  public <methods>;
}
#router
-keepnames class com.cy.router.VideoListener{
    protected <methods>;
     public <methods>;
}
-keepnames class com.cy.router.RequestListener{
    protected <methods>;
     public <methods>;
}
-keepnames class com.cy.router.LoadListener{
    protected <methods>;
     public <methods>;
}
-keepnames class com.cy.router.ContainerManager{
    protected <methods>;
     public <methods>;
}
-keepnames class com.cy.router.Container{
    protected <methods>;
     public <methods>;
}
-keepnames class com.cy.router.RouterFileProvider{
}
#protobuf
-keepnames class com.google.protobuf.**{
   *;
}
#amodule
-keepnames class com.cy.amodule.ARouterBuilderImpl{
}

#manager
-keepnames class com.cy.manager.Manager{
  protected <methods>;
  public <methods>;
}
-repackageclasses 'comcymakejar'#将混淆打乱的类放置于此包名下

未混淆的Jar是这样的
在这里插入图片描述

混淆后的Jar是这样的:
在这里插入图片描述

这时,想到如果多module生成一个aar,咋整?死丢丢可不好整,貌似小编能想到的就是自己用代码或者groovy写插件,自己合并再混淆。

文章前面已提供源码

欢迎联系、指正、批评

Github:https://github.com/AnJiaoDe

优快云:https://blog.youkuaiyun.com/confusing_awakening

OpenCV入门教程:https://blog.youkuaiyun.com/confusing_awakening/article/details/113372425

ffmpeg入门教程:https://blog.youkuaiyun.com/confusing_awakening/article/details/102007792

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值