javaee论坛

普通会员

225648

帖子

352

回复

366

积分

楼主
发表于 2017-08-24 20:37:22 | 查看: 683 | 回复: 1
在Android工程中混淆时,并不是所有的类都去混淆, 一些指定的类,我们要过滤掉不让其混淆。

在AndroidStudio中

混淆时 在 build.gradle 文件里面进行配置  

buildTypes {    debug {        // 显示Log        buildConfigField "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

-keep class okhttp3.** { *; }-keep interface okhttp3.** {*;}-dontwarn okio.**


------------------------------------------------------------------------------------------------------------------------------------------------------------------

现在我们想指定某些类不让其混淆。  有两种方法,

一种 是让不能混淆的类 继承于同一个空类 。

一种 是让不能混淆的类 实现一个空接口。

 由于类是单继承,所以当不能混淆的类已经有了父类就不适用了。 

所以采用第二种 实现自己定义的空接口, 那么实现此接口的类都可以,而且不受这种单继承限制,任何类可以实现,任何接口可以继承。 当然也是继承类和实现接口的区别中的一条重要特性


/** * Created by 张丹江 on 2016/10/24. * 实现此接口的类,都不会被混淆 */public interface DontObfuscateInterface {}

在proguard-rules.pro 文件里面这样配置 

-keep public interface com.danjiang.fastjsondemo.DontObfuscateInterface{public *;}-keep class * implements com.danjiang.fastjsondemo.DontObfuscateInterface {<methods>;<fields>;}

那么实现此接口的类都不会混淆了。

但是 还有一种情况 在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.<init>(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 <fields>;
    public <methods>;
}

然而这样违背了我们自定义的混淆接口的初衷, 这样就要对每一个具体的类的内部类在配置文件配置。 有100个含有内部类的类我们就得配置100次,有1万个就1万次,违背了我们的初衷。


然而 发现


令一种方法,就是让每一个内部类都去实现这样的 接口, 看看以往的工程,和现在的工程中都是这样做的。 临时各种实验都不成功暂且将每个内部类都实现这样的接口。 即使复杂的JavaBean 有多个内部类也要仔细的一个个去添加。。

也是没有办法,相比上一种也是简便许多 当然 当内部类数量 特别多时 都要去实现以下。

总感觉有可以解决的办法  开始分析进行各种尝试。 只让外部类实现,内部类不去实现 像这样


# 保持哪些类的子类 不被混淆-keep public class * extends android.app.Activity
#保持 Parcelable 不被混淆 以及里面的子接口  看到这里类的内部类却无法如此 除非指明报名 
-keep class * implements android.os.Parcelable {  public static final android.os.Parcelable$Creator *;}
而我们想要的是 
-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$*
或者这样
-keep class * implements com.danjiang.fastjsondemo.DontObfuscateInterface {<methods>;<fields>;}$*

或者这样

-keep class$* * implements com.danjiang.fastjsondemo.DontObfuscateInterface
或者

-keep class$* * implements com.danjiang.fastjsondemo.DontObfuscateInterface$*

理想的认为这样代表 实现此接口的类的内部类,然并卵 语法不过。各种数小时的实验 未果

-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$*
最后想到
-keep class com.danjiang.fastjsondemo.*$* {<methods>;<fields>;}
我的工程包名下面的所有类的内部类都不去混淆, 那么只需让不能混淆的 外部类实现
DontObfuscateInterface接口就可以了 
这样可以保证了不用处处配置 也不用内部类处处实现。 
当然也有个缺点就是 所有的内部类不在被混淆。 
也翻阅国外的回答,目前没有发现更强大的语法 直接支持 
-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$* 这样的效果 。 或者此类生成个变脸类 取其内部类。 
当然最后一种是目前最省事的一种写法,也有缺点内部类不在混淆。
如有高手发现其他更好的可以留言,欢迎指正不足。 详细混淆规则没有一一列举 仅仅是对 实现某个接口的类的内部类的混淆探索
邮箱 。zhangdanjiang_java@163.com


普通会员

1

帖子

328

回复

337

积分
沙发
发表于 2023-09-24 20:48:19

标记一下

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017