在Android工程中混淆时,并不是所有的类都去混淆, 一些指定的类,我们要过滤掉不让其混淆。
在AndroidStudio中
混淆时 在 build.gradle 文件里面进行配置
buildTypes {
debug {
// 显示LogbuildConfigField "boolean", "LOG_DEBUG", "true"versionNameSuffix "-debug"//混淆minifyEnabled false//签名signingConfig signingConfigs.debug
}
release {
//代码混淆开关,一定要注意现在已经使用minifyEnabled代替runProguard了minifyEnabled true//Zipalign优化zipAlignEnabled true// 移除无用的resource文件shrinkResources true// proguard-rules.pro 是当前使用的混淆文件(Eclipse中的proguard.cfg)//前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,后一个文件是自己的定义混淆文件proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}
}
//代码混淆开关,一定要注意现在已经使用minifyEnabled代替runProguard了minifyEnabled true
并不是所有的类都去混淆, 一些指定的类,我们要过滤掉不让其混淆。
首先 通常第三方开源库 是不必混淆的 也没意义。
譬如网络请求框架 okhttp.
我们在 app/proguard-rules.pro文件中配置
# 不混淆okhttp3
-keepclass okhttp3.** {*;}
-keepinterface okhttp3.** {*;}
-dontwarnokio.**
------------------------------------------------------------------------------------------------------------------------------------------------------------------
现在我们想指定某些类不让其混淆。 有两种方法,
一种 是让不能混淆的类 继承于同一个空类 。
一种 是让不能混淆的类 实现一个空接口。
由于类是单继承,所以当不能混淆的类已经有了父类就不适用了。
所以采用第二种 实现自己定义的空接口, 那么实现此接口的类都可以,而且不受这种单继承限制,任何类可以实现,任何接口可以继承。 当然也是继承类和实现接口的区别中的一条重要特性
/*** Created by 张丹江 on 2016/10/24.* 实现此接口的类,都不会被混淆*/public interfaceDontObfuscateInterface {
}
在proguard-rules.pro 文件里面这样配置
-keeppublic interface com.danjiang.fastjsondemo.DontObfuscateInterface{public *;}
-keepclass * implements com.danjiang.fastjsondemo.DontObfuscateInterface {
;;}
那么实现此接口的类都不会混淆了。
但是 还有一种情况 在fastjson解析时,有些类正常 有些类依然不正常。
FATAL EXCEPTION: main
Process: com.danjiang.fastjsondemo, PID: 21688
com.alibaba.fastjson.JSONException: default constructor not found. class com.danjiang.fastjsondemo.DataBean$a
at com.alibaba.fastjson.util.JavaBeanInfo.build(SourceFile:213)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.(SourceFile:40)
at com.alibaba.fastjson.parser.ParserConfig.createJavaBeanDeserializer(SourceFile:582)
at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(SourceFile:457)
at com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.getFieldValueDeserilizer(SourceFile:35)
说是默认构造没有找到,但是去给加了 空构造参数依然不能通过。 网上各种查询得出,是内部类被混淆的原因。
网上给出答案 ,
-keepattributesExceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
是InnerClasses 这样 就可以 然后测试 此语句无效。 其中异常给出
com.danjiang.fastjsondemo.DataBean$a 为$符号后的a 就是这个类被混淆了 然后查询内部类混淆规则
$ 代表内部类
* 代表通配符
有 这样的答案 指定报名和类名。 写死是可以的通过的
-keepnames class 包名.类名$* { public ; public ; }
然而这样违背了我们自定义的混淆接口的初衷, 这样就要对每一个具体的类的内部类在配置文件配置。 有100个含有内部类的类我们就得配置100次,有1万个就1万次,违背了我们的初衷。
然而 发现
令一种方法,就是让每一个内部类都去实现这样的 接口, 看看以往的工程,和现在的工程中都是这样做的。 临时各种实验都不成功暂且将每个内部类都实现这样的接口。 即使复杂的JavaBean 有多个内部类也要仔细的一个个去添加。。
也是没有办法,相比上一种也是简便许多 当然 当内部类数量 特别多时 都要去实现以下。
总感觉有可以解决的办法 开始分析进行各种尝试。 只让外部类实现,内部类不去实现 像这样
# 保持哪些类的子类 不被混淆-keeppublic class * extends android.app.Activity
#保持 Parcelable 不被混淆 以及里面的子接口 看到这里类的内部类却无法如此 除非指明报名
-keepclass * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}而我们想要的是-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$*或者这样-keepclass * implements com.danjiang.fastjsondemo.DontObfuscateInterface {
; ;}$*
或者这样-keepclass$* * implements com.danjiang.fastjsondemo.DontObfuscateInterface或者-keepclass$* * implements com.danjiang.fastjsondemo.DontObfuscateInterface$*
理想的认为这样代表 实现此接口的类的内部类,然并卵 语法不过。各种数小时的实验 未果-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$*最后想到-keepclass com.danjiang.fastjsondemo.*$* {
;;}我的工程包名下面的所有类的内部类都不去混淆, 那么只需让不能混淆的 外部类实现DontObfuscateInterface接口就可以了这样可以保证了不用处处配置 也不用内部类处处实现。当然也有个缺点就是 所有的内部类不在被混淆。也翻阅国外的回答,目前没有发现更强大的语法 直接支持-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$* 这样的效果 。 或者此类生成个变脸类 取其内部类。当然最后一种是目前最省事的一种写法,也有缺点内部类不在混淆。如有高手发现其他更好的可以留言,欢迎指正不足。 详细混淆规则没有一一列举 仅仅是对 实现某个接口的类的内部类的混淆探索邮箱 。zhangdanjiang_java@163.com