混淆

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

# 混淆时不使用大小写混合类名
-dontusemixedcaseclassnames
# 不跳过library中的非public的类
-dontskipnonpubliclibraryclasses
# 打印混淆的详细信息
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
# 关闭优化(原因见上边的原英文注释)
-dontoptimize
# 不进行预校验,可加快混淆速度
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

# 保留注解中的参数
-keepattributes *Annotation*
# 不混淆如下两个谷歌服务类
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
# 不混淆包含native方法的类的类名以及native方法名
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
# 不混淆View中的setXxx()和getXxx()方法,以保证属性动画正常工作
-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
# 不混淆Activity中参数是View的方法,例如,一个控件通过android:onClick="clickMethodName"绑定点击事件,混淆后会导致点击事件失效
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
# 不混淆枚举类中的values()和valueOf()方法
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 不混淆Parcelable实现类中的CREATOR字段,以保证Parcelable机制正常工作
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

# 不混淆R文件中的所有静态字段,以保证正确找到每个资源的id
-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library 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.
# 不对android.support包下的代码警告(如果我们打包的版本低于support包下某些类的使用版本,会出现警告的问题)
-dontwarn android.support.**

# Understand the @Keep support annotation.
# 不混淆Keep类
-keep class android.support.annotation.Keep

# 不混淆使用了注解的类及类成员
-keep @android.support.annotation.Keep class * {*;}

# 如果类中有使用了注解的方法,则不混淆类和类成员
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

# 如果类中有使用了注解的字段,则不混淆类和类成员
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

# 如果类中有使用了注解的构造函数,则不混淆类和类成员
-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}
  • 首先看keep类关键字:

关键字含义
keep保留类和类成员,防止被混淆或移除
keepnames保留类和类成员,防止被混淆,但没有被引用的类成员会被移除
keepclassmembers只保留类成员,防止被混淆或移除
keepclassmembernames只保留类成员,防止被混淆,但没有被引用的成员会被移除
keepclasseswithmembers保留类和类成员,防止被混淆或移除,如果指定的类成员不存在还是会被混淆
keepclasseswithmembernames保留类和类成员,防止被混淆,如果指定的类成员不存在还是会被混淆,没有被引用的类成员会被移除
  • 相关通配符:

通配符含义
*匹配任意长度字符,但不含包名分隔符.。例如一个类的全包名路径是com.othershe.test.Person,使用com.othershe.test.*com.othershe.test.*都是可以匹配的,但com.othershe.*就不能匹配
**匹配任意长度字符,并包含包名分隔符.。例如要匹配com.othershe.test.**包下的所有内容
*匹配任意参数类型。例如*** getName(***)可匹配String getName(String)
...匹配任意长度的任意类型参数。例如void setName(...)可匹配void setName(String firstName, String secondName)
<fileds>匹配类、接口中所有字段
<methods>匹配类、接口中所有方法
<init>匹配类中所有构造函数

到这里对混淆已经有了基本的了解,系统的proguard-android.txt已经为我们完成了大部分基础的混淆配置工作,至于编写当前app module下的proguard-rules.pro,只需要针对当前项目添加一些特有的配置,避免某些重要的东西被混淆掉导致错误,我们主要考虑以下几点:

  • AndroidManifest.xml中注册的继承四大组件的子类的类名以及重写的方法名都不会被混淆。
    如果希望项目中android.support.v4.app.Fragment子类的类名和重写父类的方法名不被混淆可以添加如下配置:

# 不混淆Fragment的子类类名以及onCreate()、onCreateView()方法名
-keep public class * extends android.support.v4.app.Fragment {
    public void onCreate(android.os.Bundle);
    public android.view.View onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle);
}
  • 不混淆某个特定的类和类中所有成员

-keep class com.othershe.test.utils.CommonUtil { *; }
  • 不混淆某个目录下的文件,例如使用Gson时,数据bean不能被混淆,需要如下配置:

# com.othershe.test.model代表数据bean所在的全包名目录
-keep class com.othershe.test.model.** { *; }
  • 上一条的具体原因是因为Gson用到了反射。如果我们自己使用了反射,例如

Field field = service.getField("BASE_URL");

BASE_URL是service所属类的一个字段名,则该字段不能被混淆。

  • 保留泛型

-keepattributes Signature
  • 保留用于调试堆栈跟踪的行号信息(为了后期调试方便,建议配置)

-keepattributes SourceFile,LineNumberTable

如果使用了上一行配置,还需要添加如下配置将源文件重命名为SourceFile,以便通过鼠标点击直达源文件:

-renamesourcefileattribute SourceFile
  • WebView中使用了JS调用,需要添加如下配置:

-keepclassmembers class fqcn.of.javascript.interface.for.webview {
   public *;
}
  • 项目中使用的第三方library混淆规则,列举了几个常用的:

# okhttp
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase

# Retrofit
-dontwarn okio.**
-dontwarn javax.annotation.**
-dontnote retrofit2.Platform
-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;
}

# Gson
-keep class com.google.gson.stream.** { *; }
-keepattributes EnclosingMethod
# xxx代表model类的全包名路径
-keep class xxx.** { *; }

# butterknie
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}

# eventbus
-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

以上这些可以按需添加到proguard-rules.pro

查看混淆结果

混淆后打包,会在app module/build/outputs/mapping/release目录下生成如下文件(动不动就几万行,是在没法看):

  • dump.txt:描述apk文件中所有类的内部结构

  • mapping.txt:混淆前后的类、类成员、方法的对照关系(重要,追溯Crash堆栈信息要用到)

  • resources.txt:资源文件的压缩信息

  • seeds.txt:未被混淆的类和成员

  • usage.txt:被移除的代码

 

转载于:https://my.oschina.net/u/3959225/blog/2235754

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值