Android 开启混淆后序列化的问题 Parcelable encountered IOException writing serializable

778 阅读1分钟

前言

最近项目中遇到一个棘手的问题 在打包打开混淆以后 一直报序列化的问题 我是用的Bundle传输的数据 我开启了序列化混淆 也忽略了实体类 还是报错~~~~

昨天加班到12点多 经过不断的查资料 不断的尝试 最终解决了这个bug 在此记录一下心酸过程...

2

错误提示及定位

21221-21221/com.app.ldy.mymvvm E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.app.ldy.mymvvm, PID: 21221
    1.//这里加备注 方便看 主要看这里
    java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.app.ldy.mymvvm.data.bean.Item00)
        at android.os.Parcel.writeSerializable(Parcel.java:2116)
        at android.os.Parcel.writeValue(Parcel.java:1886)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:978)
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1629)
        at android.os.Bundle.writeToParcel(Bundle.java:1303)
        at android.os.Parcel.writeBundle(Parcel.java:1047)
        at android.content.Intent.writeToParcel(Intent.java:10866)
        at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:3917)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1731)
        at android.app.ContextImpl.startActivity(ContextImpl.java:1033)
        at android.app.ContextImpl.startActivity(ContextImpl.java:1004)
        at android.content.ContextWrapper.startActivity(ContextWrapper.java:414)
        at me.hgj.mvvmhelper.ext.CommExtKt.e(:88)
        at com.app.ldy.mymvvm.ui.fragment.PhotoFragment.S(:61)
        at com.app.ldy.mymvvm.ui.fragment.PhotoFragment.Q(Unknown Source:0)
        at t.c.a(Unknown Source:2)
        at com.chad.library.adapter.base.BaseQuickAdapter.U(:596)
        at com.chad.library.adapter.base.BaseQuickAdapter$b.onClick(:538)
        at android.view.View.performClick(View.java:7704)
        at android.view.View.performClickInternal(View.java:7677)
        at android.view.View.access$3600(View.java:850)
        at android.view.View$PerformClick.run(View.java:29120)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:236)
        at android.app.ActivityThread.main(ActivityThread.java:8087)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011)
        2.//这里加备注 方便看 主要看这里
     Caused by: java.io.NotSerializableException: com.google.gson.internal.LinkedTreeMap$a
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)

错误1

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.app.ldy.mymvvm.data.bean.Item00)Parcelable在写入可序列化对象时遇到IOException·

在项目中 这个Item00的子类我也实现了序列化接口了 2 可以感觉截图看到 我们所有的内部类均实现了serializable 发现不是这里的错误 继续根据错误提示 排查问题

问题2

Caused by: java.io.NotSerializableException: com.google.gson.internal.LinkedTreeMap

这个错误 根据名称也可以分析是序列化的问题 但是具体是什么错误 不得而知 还得继续查资料3

翻阅 stack overflow我们查到了和这个问题一样的帖子 内心很激动 像是迷路的孩子找到了指明灯 2 根据问题 找到点赞较高的一个回复 33

还是混淆规则的问题 有关LinkedTreeMap 写入和读取 没有给予混淆规则说明 导致数据内部 序列化的时候出现错误 非常不好排查

解决方案

以上都是解决问题的出发点和思路 具体解决方法 其实很简单 但是这个原因 还需要自己摸索 通过资料一点点追求原因 我在andrdroid proguard-rules.pro 新增了关于 序列化写入和读取的规则

# Explicitly preserve all serialization members. The Serializable interface 
# is only a marker interface, so it wouldn't save them.

#显式保留所有序列化成员。可序列化接口 #只是一个标记接口,所以不能保存它们。

关于序列化写入和读取混淆规则如下(解决问题方案 在配置里加入以下规则)

# 显式保留所有序列化成员。可序列化接口只是一个标记接口,因此不会保存它们。
-keep public class * implements java.io.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();
}

有关Parcelable,Serializable序列化规则 以下是原有的配置

-keepnames class * implements java.io.Serializable
-keepattributes Signature
-keep class **.R$* {*;}
-ignorewarnings
-keepclassmembers class **.R$* {
    public static <fields>;
}

总结

遇到一个很难解决的bug 往往需要付出大量的时间 从一些提示或很细小的发现 一步步深入排查 只要有解决bug的决心 结果往往都是好的 问题解决后 心情也是格外的开朗 2222