Unmarshalling посылки код неизвестного типа

Мы получаем эту ошибку в отчетах о сбоях, зарегистрированных магазином игр. Не могу воспроизвести это во всех наших тестах. Есть ли у кого-нибудь еще такая же проблема или решение? Дело в том, что мы даже не знаем, что делать, чтобы воспроизвести этот баг.

Для всех объектов Parcelable определены CREATOR, writeToParcel() и конструктор. Все списки и сложные типы инициализируются и проверяются на нуль.

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

person Manoj Gopal    schedule 30.10.2013    source источник
comment
Имея очень похожее исключение после включения proguard, я еще не решил себя.   -  person Rolf ツ    schedule 04.11.2013
comment
Обнаружил в некоторых местах, что мы либо неправильно упорядочивали поля, либо пропускали некоторые поля между create/constructor и writeToParcel. Также добавил CREATOR ко всем вложенным классам, и он исчез. Лучше всего разделить экран одним и тем же файлом и сопоставить каждое поле для каждого вложенного класса в каждом из методов. Ужасная работа, но больше не вижу этой ошибки.   -  person Manoj Gopal    schedule 22.01.2014
comment
Может быть, это может помочь кому-то. Включение режима разработчика и постоянное уничтожение действий помогает воспроизвести это в 100% случаев.   -  person Aerim    schedule 29.03.2021


Ответы (7)


У меня возникла проблема с пользовательским представлением, имеющим собственную реализацию View.BaseSavedState. Оказалось, что метод writeToParcel() имеет вызовы методов в неправильном порядке.

Обнаружение проблемы было раздражающим, и мне нужно было выполнить пошаговую отладку Android SDK вплоть до класса Bundle, где вызывается unparcel():

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) будет читать их в том порядке, в котором они были написаны, но если у вас есть пользовательские представления или объекты, если они были записаны в порядке, отличном от того, в котором вы их сейчас читаете, что-то не так произойдет в СЛЕДУЮЩИЙ элемент для чтения.

Итак, я нашел проблему, определив последний элемент, который был успешно прочитан. Обычно вы можете определить это (если это настраиваемое представление или объект), проверив имя класса создателя. Проверьте метод readParcelableCreator() класса Parcel:

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

Вы можете проверить строку имени для класса создателя. Если это пользовательский, вы можете сразу определить его. Затем, если при следующем чтении произойдет сбой вашего приложения, вы можете быть почти уверены, что виновником было предыдущее чтение.

Надеюсь, поможет.

person Ricardo    schedule 14.11.2013
comment
Я понял ваше объяснение, но не совсем понял, как это отлаживать :) любая помощь? Я дважды проверил все мои SavedStates и заказы в порядке. - person natario; 09.01.2016
comment
Я предложил решение не % 100 работает для меня, но это дало мне возможность исследовать пользовательскую реализацию View.BaseSavedState, которая у меня есть в одном из пользовательских представлений. - person Hadi Tok; 29.06.2017

Я также получил эту ошибку, но я нашел проблему. Я изменил переменную с long на int, но забыл изменить следующее:

У меня было parcel.writeLong(number), а потом я прочитал это как number=parcel.readInt(). Правильно parcel.writeInt(number).

person Json    schedule 30.05.2014
comment
Точная ошибка, которую я совершал! - person Sufian; 20.06.2015
comment
Моя ошибка заключалась в том, что я делал парцеллу.writeValue(объект) в сочетании с парцеллой.readParcelable(Class.class.getClassLoader()). Пришлось использовать посылка.writeParcelable() и посылка.readParcelable() - person Pedro Romão; 26.02.2019

Проверьте порядок ваших read и write в ваших классах Parcelable и соответствующих подклассах.

Порядок, в котором вы writeToParcel, должен быть таким же, как вы читали в своем MyParcelable(Parcel in) методе.

person HyperionX    schedule 14.02.2017
comment
Это был правильный ответ для меня! Спасибо @Блейк - person Lubomir Babev; 19.10.2017

Я получил эту ошибку, когда перечитывал исходный код 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);
}
person Bruno Peres    schedule 17.07.2014

У меня возникла такая же ошибка при прочтении посылки.

Проверяйте порядок и количество при чтении/записи ваших классов Parcelable и соответствующих подклассов.

person Karen Chang    schedule 08.08.2017

Если у вас есть собственный класс SavedState, убедитесь, что он не является Proguarded и не имеет статического атрибута CREATOR.

Используйте что-то вроде:

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

В моем случае я пытался присвоить список массивов списку, и это вызывает эту ошибку.

person Sergio Morales    schedule 03.05.2018