【问题标题】:Parcel Unmarshalling unknown type code包裹解组未知类型代码
【发布时间】:2018-05-04 05:09:19
【问题描述】:

我们在 Play 商店记录的崩溃报告中收到此错误。无法在我们所有的测试中复制这一点。有没有其他人有同样的问题或解决方案? 问题是,我们甚至不知道如何复制这个错误。

所有 Parcelable 对象都定义了 CREATOR、writeToParcel() 和 contructor。所有列表和复杂类型都已初始化并检查是否为空。

java.lang.RuntimeException: Unable to start activity ComponentInfo{au.com.company/au.com.company.DetailsActivity}: java.lang.RuntimeException: Parcel android.os.Parcel@42d6e270: Unmarshalling unknown type code 6881381 at offset 11268
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2247)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2297)
at android.app.ActivityThread.access$700(ActivityThread.java:152)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1282)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5328)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@42d6e270: Unmarshalling unknown type code 6881381 at offset 11268
at android.os.Parcel.readValue(Parcel.java:2032)
at android.os.Parcel.readMapInternal(Parcel.java:2225)
at android.os.Bundle.unparcel(Bundle.java:223)
at android.os.Bundle.getSparseParcelableArray(Bundle.java:1240)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:861)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1104)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1086)
at android.support.v4.app.FragmentManagerImpl.dispatchCreate(SourceFile:1872)
at android.support.v4.app.FragmentActivity.onCreate(SourceFile:215)
at android.support.v7.app.ActionBarActivity.onCreate(SourceFile:97)
at au.com.company.DetailsActivity.onCreate(SourceFile:40)
at android.app.Activity.performCreate(Activity.java:5250)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1097)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
... 11 more

【问题讨论】:

  • 启用proguard后有一个非常相似的异常,还没有解决我的问题。
  • 在某些地方发现我们要么对字段排序错误,要么在 create/constructor 和 writeToParcel 之间缺少某些字段。还将 CREATOR 添加到所有嵌套类中,然后它就消失了。最好是用同一个文件分割屏幕,并在每个方法中匹配每个嵌套类的每个字段。令人毛骨悚然的工作,但不再看到该错误。
  • 也许这可以帮助某人。启用开发者模式并始终终止活动有助于 100% 重现此情况

标签: android exception unmarshalling parcelable parcel


【解决方案1】:

我遇到了一个自定义视图有自己的 View.BaseSavedState 实现的问题。事实证明,那里的 writeToParcel() 方法的方法调用顺序错误。

发现问题很烦人,我需要逐步调试 Android SDK 到调用 unparcel() 的 Bundle 类:

synchronized void unparcel() {
    if (mParcelledData == null) {
        return;
    }

    int N = mParcelledData.readInt();
    if (N < 0) {
        return;
    }
    if (mMap == null) {
        mMap = new HashMap<String, Object>(N);
    }
    mParcelledData.readMapInternal(mMap, N, mClassLoader);
    mParcelledData.recycle();
    mParcelledData = null;
}

日志的第 223 行正是 readMapInternal() 调用。 Parcel 对象将在此处迭代其项目,并一一读取值。如果某些内容以错误的顺序写入,通常会出现问题。 Parcel.readValue(ClassLoader loader) 方法将按照它们写入的顺序读取它们,但是如果您有自定义视图或对象,如果它们的写入顺序与您现在正在读取它们的顺序不同,则会在下一个要阅读的项目。

所以我通过识别最后一个成功读取的项目发现了问题。您通常可以通过检查其创建者类名称来识别它(如果它是自定义视图或对象)。检查 Parcel 类的方法 readParcelableCreator():

public final <T extends Parcelable> Parcelable.Creator<T> readParcelableCreator(
        ClassLoader loader) {
    String name = readString();
    if (name == null) {
        return null;
    }
...
}

您可以检查创建者类的名称字符串。如果是定制的,您可以立即识别它。然后,如果下一次阅读使您的应用程序崩溃,您几乎可以确定罪魁祸首是上一次阅读。

希望对你有帮助。

【讨论】:

  • 我明白了你的解释,但还不太明白如何调试这些东西 :) 有什么帮助吗?我已经仔细检查了我所有的 SavedStates 并且订单正常。
  • 我建议的解决方案 %100 对我不起作用,但它让我调查了我在自定义视图之一上的自定义 View.BaseSavedState 实现。
【解决方案2】:

我也遇到了这个错误,但我发现了问题。我已将变量从 long 更改为 int,但忘记更改以下内容:

我有parcel.writeLong(number),然后读回number=parcel.readInt()。正确的是parcel.writeInt(number)。

【讨论】:

  • 我所犯的确切错误!
  • 我的错误是将 parcel.writeValue(object) 与 parcel.readParcelable(Class.class.getClassLoader()) 结合使用。不得不使用 parcel.writeParcelable() 和 parcel.readParcelable()
【解决方案3】:

在 Parcelable 类和各自的子类中检查 read 和 write 的顺序。

writeToParcel 的顺序应与您在 MyParcelable(Parcel in) 方法中读取的顺序相同。

【讨论】:

  • 这对我来说是正确的答案!谢谢@Blake
【解决方案4】:

我在阅读 Parcel 源时收到此错误,以保存在地图上而不是检查返回值是否为空:

String tag = in.readString();
Double value = in.readDouble();
while (tag != null && value != null) {
    this.observations.put(tag, value);
    tag = in.readString();
    value = in.readDouble();
};

应该存储一个 int 用于在 Parcel 上正确迭代:

int numObservations = in.readInt();
String key;
Double value;
for (int i = 0; i < numObservations; i++) {
    key = in.readString();
    value = in.readDouble();
    map.put(tag, value);
}

【讨论】:

    【解决方案5】:

    我在读取包裹时发生了同样的错误。

    在读/写 Parcelable 类和相应的子类时检查顺序和计数。

    【讨论】:

      【解决方案6】:

      如果您有自己的 SavedState 类,请确保它不是 Proguarded,也不是 CREATOR 静态属性。

      使用类似的东西:

      # Keeping *SavedState and *SavedState#CREATOR
      -keep public final class * extends android.view.AbsSavedState
      -keepclassmembers public final class * extends android.view.AbsSavedState { *; }
      

      【讨论】:

        【解决方案7】:

        在我的情况下,我试图将一个 arrayList 分配给一个 List 并触发该错误

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-04-08
          • 1970-01-01
          • 1970-01-01
          • 2011-05-10
          • 1970-01-01
          • 2020-06-01
          • 1970-01-01
          相关资源
          最近更新 更多