Android混淆

 在此处添加特定于项目的ProGuard规则。
# 您可以使用build.gradle中的proguardFiles设置来控制应用的配置文件集
# For more details, see 有关详细信息,请参见
#   http://developer.android.com/guide/developing/tools/proguard.html
# 如果您的项目使用带有JS的WebView,请取消注释以下内容并为JavaScript接口类指定完全限定的类名:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
# }
# 取消注释此项以保留用于调试堆栈跟踪的行号信息。
#-keepattributes SourceFile,LineNumberTable
# 如果保留行号信息,请取消注释以隐藏原始源文件名。
#-renamesourcefileattribute SourceFile
#===================================================================================================
# 混淆的四步骤,压缩 shrinker,优化 Optimizer,混淆 Obfuscator,预校验 Preverifier
# 第一步:删除无效的类,字段,方法等。等二步:优化字节码,合并方法,删除无用字段等
# 第三步:将类名,属性名,方法名,以及字段名混淆为难以读懂的字母,比如a,b,c等。
# 第四步:对class文件进行预检验,确保虚拟机加载的class文件是安全并且可以执行的
# 混淆官方文档关于Android 例子:https://www.guardsquare.com/en/products/proguard/manual/examples
# 成功打包后会在目录*** app\build\outputs\mapping\release 下生成几个文件
# dump.txt 混淆后类的内部结构说明;
# usage.txt :经过压缩过程被删除的类、方法、字段。
# mapping.txt :存储经过混淆过程,新旧类名、方法名、字段名的映射,软件发布一定要保留此文件,
#               不然收集上来的报错信息,不知道具体是哪个类或方法,你将会很是头疼。
#               mapping.txt 这个文件可以同sdk下:Sdk\tools\proguard\bin\retrace.bat + 错误日志 反推
#                出正确错误信息 详细使用:https://www.jianshu.com/p/86ee6ef970ef,还可以使用proGuard工具GUI反推
# seeds.txt :被 Keep 规则匹配到的类、方法、字段,来验证我们的 keep 规则是否合我们的需求。
#我个人认为混淆规则是由:keep规则,过滤器,其他的选项,构成
#压缩Skrinking:默认开启,用以减少应用体积,移除未被使用的类和成员,并且会在优化动作执行后再次执行
#(因为优化后可能会再次暴露一些未被使用的类和成员)-dontshrink 关闭压缩
#-dontshrink
#优化(Optimization):默认开启,在字节码级别执行优化,让应用运行的更快。-dontoptimize 关闭优化
#-dontoptimize
#混淆(Obfuscation):默认开启,增大反编译难度,类和类成员会被随机命名,除非用keep保护。-dontobfuscate 关闭混淆
#-dontobfuscate
#关键字   描述
#keep  保留类和类中的成员,防止它们被混淆或移除。
#keepnames 保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。
#keepclassmembers  只保留类中的成员,防止它们被混淆或移除。
#keepclassmembernames  只保留类中的成员,防止它们被混淆,但当成员没有被引用时会被移除。
#keepclasseswithmembers    保留类和类中的成员,防止它们被混淆或移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。
#keepclasseswithmembernames    保留类和类中的成员,防止它们被混淆,但当成员没有被引用时会被移除,前提是指名的类中的成员必须存在,如果不存在则还是会混淆。
#通配符   描述
#   匹配类中的所有字段
#  匹配类中的所有方法
#    匹配类中的所有构造函数
#* 匹配任意长度字符,但不含包名分隔符(.)。比如说我们的完整类名是com.example.test.MyActivity,使用com.*,或者com.exmaple.*都是无法匹配的,因为*无法匹配包名中的分隔符,正确的匹配方式是com.exmaple.*.*,或者com.exmaple.test.*,这些都是可以的。但如果你不写任何其它内容,只有一个*,那就表示匹配所有的东西。
#**    匹配任意长度字符,并且包含包名分隔符(.)。比如proguard-android.txt中使用的-dontwarn android.support.**就可以匹配android.support包下的所有内容,包括任意长度的子包。
#***   匹配任意参数类型。比如void set*(***)就能匹配任意传入的参数类型,*** get*()就能匹配任意返回值的类型。
#… 匹配任意长度的任意类型参数。比如void test(…)就能匹配任意void test(String a)或者是void test(int a, String b)这些方法。
#-keep class XXXX
#保留类名不变,也就是类名不混淆,而类中的成员名不保证。当然也可以是继承XXX类的所有类名不混淆,
#具体代码不贴了,重在理解。
#
#-keepclasseswithmembers class XXXX
#保留类名和成员名。当然也可以是类中特定方法,代码不贴了,理由同上。
# =============================================默认=================================================
# android studio版本是不一样app\build\imtermediates\proguard-files\proguard-android-optmize.txt或proguard-android.txt
# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html
#
# Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with
# the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and
# will be ignored by new version of the Android plugin for Gradle.

# Optimizations: If you don't want to optimize, use the proguard-android.txt configuration file
# instead of this one, which turns off the optimization flags.
# Adding optimization introduces certain risks, since for example not all optimizations performed by
# ProGuard works on all versions of Dalvik.  The following flags turn off various optimizations
# known to have issues, but the list may not be complete or up to date. (The "arithmetic"
# optimization can be used if you are only targeting Android 2.0 or later.)  Make sure you test
# thoroughly if you go this route.
#-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
#-optimizationpasses 5
#优化时允许访问并修改有修饰符的类和类的成员
#-allowaccessmodification
#
#-dontusemixedcaseclassnames
#-dontskipnonpubliclibraryclasses
#-verbose

# Preserve some attributes that may be required for reflection.
#-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod
#
#-keep public class com.google.vending.licensing.ILicensingService
#-keep public class com.android.vending.licensing.ILicensingService
#-keep public class com.google.android.vending.licensing.ILicensingService
#-dontnote com.android.vending.licensing.ILicensingService
#-dontnote com.google.vending.licensing.ILicensingService
#-dontnote com.google.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
#-keepclasseswithmembernames class * {
#    native ;
#}

# Keep setters in Views so that animations can still work.
#-keepclassmembers public class * extends android.view.View {
#    void set*(***);
#    *** get*();
#}

# We want to keep methods in Activity that could be used in the XML attribute onClick.
#-keepclassmembers class * extends android.app.Activity {
#    public void *(android.view.View);
#}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
#-keepclassmembers enum * {
#    public static **[] values();
#    public static ** valueOf(java.lang.String);
#}

#-keepclassmembers class * implements android.os.Parcelable {
#    public static final ** CREATOR;
#}

#-keepclassmembers class **.R$* {
#    public static ;
#}

# Preserve annotated Javascript interface methods.
#-keepclassmembers class * {
#    @android.webkit.JavascriptInterface ;
#}

# The support libraries contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
#-dontnote android.support.**
#-dontnote androidx.**
#-dontwarn android.support.**
#-dontwarn androidx.**

# This class is deprecated, but remains for backward compatibility.
#-dontwarn android.util.FloatMath

# Understand the @Keep support annotation.
#-keep class android.support.annotation.Keep
#-keep class androidx.annotation.Keep

#-keep @android.support.annotation.Keep class * {*;}
#-keep @androidx.annotation.Keep class * {*;}

#-keepclasseswithmembers class * {
#    @android.support.annotation.Keep ;
#}

#-keepclasseswithmembers class * {
#    @androidx.annotation.Keep ;
#}

#-keepclasseswithmembers class * {
#    @android.support.annotation.Keep ;
#}

#-keepclasseswithmembers class * {
#    @androidx.annotation.Keep ;
#}

#-keepclasseswithmembers class * {
#    @android.support.annotation.Keep (...);
#}

#-keepclasseswithmembers class * {
#    @androidx.annotation.Keep (...);
#}

# These classes are duplicated between android.jar and org.apache.http.legacy.jar.
#-dontnote org.apache.http.**
#-dontnote android.net.http.**

# These classes are duplicated between android.jar and core-lambda-stubs.jar.
#-dontnote java.lang.invoke.**
# ===========================================默认的=================================================

#===========================================基本不用动区域==========================================
#------基本指令区---------
#指定压缩级别代码混淆压缩比,在0和7之间,默认为5
#默认-optimizationpasses 5
-dontskipnonpubliclibraryclassmembers
-printmapping proguardMapping.txt
#混淆时采用的算法 指定混淆时采用的算法,后面的参数是一个过滤器 这个过滤器是谷歌推荐的算法,一般不改变
#默认-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#备用-optimizations !code/simplification/cast,!field/*,!class/merging/*
#默认已经有了-keepattributes *Annotation*,InnerClasses
#保持泛型 避免混淆泛型,这在JSON实体映射时非常重要,比如fastJson
-keepattributes Signature
#保留行号 抛出异常时保留代码行号,在异常分析中可以方便定位
-keepattributes SourceFile,LineNumberTable
#将文件来源重命名为“SourceFile”字符串 如果保留行号信息,请取消注释以隐藏原始源文件名。
-renamesourcefileattribute SourceFile

#把混淆类中的方法名也混淆了
#-useuniqueclassmembernames
# Android不需要preverify,不做预校验,preverify是proguard的4个步骤之一 去掉这一步可加快混淆速度
-dontpreverify
#优化时允许访问并修改有修饰符的类和类的成员
#默认-allowaccessmodification
#------基本指令区---------

#------默认保留区---------
# 保留了继承自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 class android.support.** {*;}

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

# 保留自定义控件(继承自View)不被混淆
-keep public class * extends android.view.View {
    *** get*();
    void set*(***);
    public (android.content.Context);
    public (android.content.Context, android.util.AttributeSet);
    public (android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
    public (android.content.Context, android.util.AttributeSet);
    public (android.content.Context, android.util.AttributeSet, int);
}
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
#保持所有实现 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();
}

-keep class **.R$* {
 *;
}
# 对于带有回调函数onXXEvent的,不能被混淆
-keepclassmembers class * {
    void *(**On*Event);
}
#------默认保留区--------
#-------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);
}
#------webview----------

#------ 保持测试相关的代码---
#-dontnote junit.framework.**
#-dontnote junit.runner.**
#-dontwarn android.test.**
#-dontwarn android.support.test.**
#-dontwarn org.junit.**
#------ 保持测试相关的代码---
#===================================================================================================
#===========================================定制化区域==============================================
#---------1.实体类-----------
#将你项目中实体类都拎出来,用以下语法进行保留。
#-keep class 你的实体类所在的包.** { *; }
#如我的项目下类User的完整路径为:com.demo.login.bean.User, 那我的混淆如下
#-keep class com.demo.login.bean.** { *; }
#当然你的实体类肯定不止这一个,请用上边的方式一一添加,如果你的实体类都在一个包下,那你就幸福了。
#例子:
#-keep class com.demo.login.bean.** { *; }
#-keep class com.demo.main.bean.** { *; }

#保留实体类和成员被混淆
#对于实体,保留它们的set和get方法,对于boolean型get方法,有人喜欢命名isXXX的方式,所以不要遗漏。如下:
# 保留实体类和成员不被混淆
#例子:-keep public class com.xxxx.entity.** {
#public void set*(***);
#public *** get*();
#public *** is*();
#}
# 如果有引用android-support-v4.jar包,可以添加下面这行
#例子:-keep public class com.xxxx.app.ui.fragment.** {*;}


-keep public final class BuildConfig

-keep class com.example.MyClass
-keep class com.example.MyClassToo

#---------1.实体类-----------

#--------2.第三方包----------
#打开你的build.gradle文件,查看你用了哪些第三方的包。
#dependencies {
#    compile 'com.github.bumptech.glide:glide:3.7.0'
#    compile 'org.greenrobot:eventbus:3.0.0'
#}
#我这里用了glide,eventbus。我去他们的官网把已经写好的混淆copy下来。

#一般官网都是有混淆的,没有的话就google,也没有的话自己按照上面的写法自己写,
#还不会的话。。。。。只能换个包。。。。。如果你是直接包含的jar包的话,你这样写
#log4j
#-libraryjars log4j-1.2.17.jar
#-dontwarn org.apache.log4j.**
#-keep class  org.apache.log4j.** { *;}
#大致意思就是不混淆,不报warn。如果gradle报错的话,可以考虑注释掉-libraryjars log4j-1.2.17.jar这句。

#其他的第三方jar包的解决方案
#这个就取决于第三方包的混淆策略了,一般都有在各自的SDK中有关于混淆的说明文字,比如支付宝如下:
# 对alipay的混淆处理
#-libraryjars libs/alipaysdk.jar
#-dontwarn com.alipay.android.app.**
#-keep public class com.alipay.**  { *; }
#值得注意的是,不是每个第三方SDK都需要
#-dontwarn 指令,这取决于混淆时第三方SDK是否出现警告,需要的时候再加上。

#针对第三方jar包的解决方案
#
#我们在Android项目中不可避免要使用很多第三方提供的SDK,一般而言,这些SDK是经过ProGuard混淆的,
#而我们所需要做的就是避免这些SDK的类和方法在我们APP被混淆。
## 针对android-support-v4.jar的解决方案
#-libraryjars libs/android-support-v4.jar
#-dontwarn android.support.v4.**
#-keep class android.support.v4.**  { *; }
#-keep interface android.support.v4.app.** { *; }
#-keep public class * extends android.support.v4.**
#-keep public class * extends android.app.Fragment

#eventBus
#-keepattributes *Annotation*
#-keepclassmembers class ** {
#    @org.greenrobot.eventbus.Subscribe ;
#}
#-keep enum org.greenrobot.eventbus.ThreadMode { *; }
#-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
#    (java.lang.Throwable);
#}
#
##glide
#-keep public class * implements com.bumptech.glide.module.GlideModule
#-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
#  **[] $VALUES;
#  public *;
#}
#
##log4j
#-libraryjars log4j-1.2.17.jar
#-dontwarn org.apache.log4j.**
#-keep class  org.apache.log4j.** { *;}


#--------2.第三方包----------

#-------3.与js互相调用的类--------
#与js互调的类,工程中没有直接跳过。一般你可以这样写
#-keep class 你的类所在的包.** { *; }
#如果是内部类的话,你可以这样
#-keepclasseswithmembers class 你的类所在的包.父类$子类 { ; }
#例如
#-keepclasseswithmembers class com.demo.login.bean.ui.MainActivity$JSInterface {
#      ;
#}

#对JavaScript的处理
# 保留JS方法不被混淆
#例子:-keepclassmembers class com.example.xxx.MainActivity$JSInterface1 {
#;
#}
# 其中JSInterface是MainActivity的子类
#例子:-keepclasseswithmembers class com.demo.login.bean.ui.MainActivity$JSInterface {
#      ;
#}

#-------3.与js互相调用的类--------

#-------4.反射相关的类和方法--------
#与反射有关的类,工程中没有直接跳过。类的话直接这样
#-keep class 你的类所在的包.** { *; }


#-------4.反射相关的类和方法--------
#===========================================定制化区域==============================================


# 一种好的做法是把所有实体都放在一个包下进行管理,这样只写一次混淆就够了,
# 避免以后在别的包中新增的实体而忘记保留,代码在混淆后因为找不到相应的实体类而崩溃。
# 如果有引用android-support-v4.jar包,可以添加下面这行
#例子:-keep public class com.xxxx.app.ui.fragment.** {*;}

#内嵌类
#内嵌类经常会被混淆,结果在调用的时候为空就崩溃了,最好的解决方法就是把这个内嵌类拿出来,
#单独成为一个类。如果一定要内置,那么这个类就必须在混淆的时候保留,比如如下:
# 保留内嵌类不被混淆-keep class com.example.xxx.MainActivity$* { *; }
#这个$符号就是用来分割内嵌类与其母体的标志。

#处理反射
#在程序中使用SomeClass.class.method这样的静态方法,在ProGuard中是在压缩过程中被保留的,
#那么对于Class.forName("SomeClass")呢,SomeClass不会被压缩过程中移除,
#它会检查程序中使用的Class.forName方法,对参数SomeClass法外开恩,不会被移除。但是在混淆过程中,
#无论是Class.forName("SomeClass"),还是SomeClass.class,都不能蒙混过关,SomeClass这个类名称会被混淆,
#因此,我们要在ProGuard.cfg文件中保留这个类名称。
#Class.forName("SomeClass")
#SomeClass.class
#SomeClass.class.getField("someField")
#SomeClass.class.getDeclaredField("someField")
#SomeClass.class.getMethod("someMethod", new Class[] {})
#SomeClass.class.getMethod("someMethod", new Class[] { A.class })
#SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })
#SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})
#SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })
#SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })
#AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
#AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
#AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")
#在混淆的时候,要在项目中搜索一下上述方法,将相应的类或者方法的名称进行保留而不被混淆。

#对于自定义View的解决方案
#但凡在Layout目录下的XML布局文件配置的自定义View,都不能进行混淆。为此要遍历Layout下的所有的XML布局文件,
#找到那些自定义View,然后确认其是否在ProGuard文件中保留。有一种思路是,在我们使用自定义View时,
#前面都必须加上我们的包名,比如com.a.b.customeview,我们可以遍历所有Layout下的XML布局文件,
#查找所有匹配com.a.b的标签即可。

#其他注意事项
#当然在使用ProGuard过程中,还有一些注意的事项,如下。
#1,如何确保混淆不会对项目产生影响
#测试工作要基于混淆包进行,才能尽早发现问题
#每天开发团队的冒烟测试,也要基于混淆包
#发版前,重点的功能和模块要额外的测试,包括推送,分享,打赏

#打包时忽略警告
#当导出包的时候,发现很多could not reference class之类的warning信息,
#如果确认App在运行中和那些引用没有什么关系,可以添加-dontwarn 标签,就不会提示这些警告信息了

#对于自定义类库的混淆处理
#比如我们引用了一个叫做AndroidLib的类库,我们需要对Lib也进行混淆,
#然后在主项目的混淆文件中保留AndroidLib中的类和类的成员。

#使用annotation避免混淆
#另一种类或者属性被混淆的方式是,使用annotation,比如这样:
#@keep
#@keep PublicGetterSetters
#public class Bean{
# public  boolean booleanProperty;
# public  int intProperty;
# public  String stringProperty;
#}

#在项目中指定混淆文件
#到最后,发现没有介绍如何在项目中指定混淆文件。
#在项目中有一个project.properties文件,在其中写这么一句话,
#就可以确保每次手动打包生成的apk是混淆过的。
#proguard.config=proguard.cfg
#其中,proguard.cfg是混淆文件的名称。
#小结
#
#总之ProGuard是一个比较枯燥的过程,但Android项目没有了ProGuard就真不行了,
#这样可以保证我们开发出的APK可以更健壮,毕竟很多核心代码质量也算是一个APK的核心竞争力吧。

你可能感兴趣的:(android)