Как найти источник сбоев типа java.lang.RuntimeException: Parcel android.os.Parcel@####: Отмена указания неизвестного кода типа XXXX со смещением YYY

1

Наша система отчетов о сбоях регистрирует сбои этого типа:

Caused by java.lang.RuntimeException: Parcel android.os.Parcel@8bf0d1f: Unmarshalling unknown type code 6881391 at offset 356
   at android.os.Parcel.readValue(Parcel.java:2779)
   at android.os.Parcel.readSparseArrayInternal(Parcel.java:3148)
   at android.os.Parcel.readSparseArray(Parcel.java:2362)
   at android.os.Parcel.readValue(Parcel.java:2757)
   at android.os.Parcel.readArrayMapInternal(Parcel.java:3067)
   at android.os.BaseBundle.unparcel(BaseBundle.java:257)
   at android.os.Bundle.getSparseParcelableArray(Bundle.java:958)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1329)
   at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
   at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3244)
   at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:3194)
   at android.support.v4.app.Fragment.restoreChildFragmentState(Fragment.java:1444)
   at android.support.v4.app.Fragment.onCreate(Fragment.java:1415)
   at com.payments.base.BaseFragment.onCreate(BaseFragment.java:68)
   at com.payments.app.fragments.TopLevelFragment.onCreate(TopLevelFragment.java:422)
   at android.support.v4.app.Fragment.performCreate(Fragment.java:2331)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1386)
   at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
   at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3244)
   at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:3194)
   at android.support.v4.app.Fragment.restoreChildFragmentState(Fragment.java:1444)
   at android.support.v4.app.Fragment.onCreate(Fragment.java:1415)

Что я знаю: это происходит, когда приложение восстанавливается из фона, и вызывается onCreate. Наше приложение представляет собой приложение Single-Activity со всем пользовательским интерфейсом, управляемым фрагментами. Этот сбой встречается редко, и его очень трудно воспроизвести в нашей среде разработки.

Кроме того - я не верю, что причина в том, что мы создали какой-то пакетный объект, скорее перезагрузка компонента Android, но не уверен.

Что я хотел бы знать: как проанализировать эти следы стека, чтобы определить причину? как использовать предоставленные данные?

Обратите внимание, что трассировка стека едва ли указывает на какую-либо конкретную строку в нашем приложении, а где она делает - только на методы onCreate нашей деятельности и фрагментирует базовые классы

Теги:
parcelable

2 ответа

0

По моему опыту, такая ошибка связана не столько с тем, что происходит при возникновении ошибки, сколько с тем, что происходило ранее в вашем приложении. В частности, когда приложение ушло в фоновый режим.

Но, начиная с того, что показывает трассировка стека. TopLevelFragment восстанавливается из предыдущего состояния. Во время этого восстановления восстанавливаются дочерние фрагменты TopLevelFragment. При восстановлении дочерних фрагментов сохраненное состояние фрагмента одного из фрагментов пытается разархивировать себя, когда getSparseParcelableArray() вызывается в Bundle для получения сохраненного фрагмента состояния просмотра. Это происходит в FragmentManager.java, строка 1329. Что-то в состоянии сохраненного фрагмента, что Parcel не знает, что делать, так как он демарширует себя.

Чтобы сузить, на каком дочернем фрагменте TopLevelFragment вы должны сосредоточиться, я бы поставил точку останова в строке 1329 FragmentManager.java и проверил тип Fragment f is. Имейте в виду, что у вас может быть несколько дочерних фрагментов, которые будут восстановлены, поэтому вы хотите увидеть, какой фрагмент не может пройти после строки 1329.

Но, конечно, вы должны заставить эту логику восстановления происходить последовательно. Если вы просто отправите свое приложение в фоновый режим и вернете его на передний план, этого, вероятно, не произойдет. Таким образом, вы можете делать то, что предлагает Ричард Р, и использовать опцию разработчика "Не держать действия", чтобы заставить Android уничтожать и восстанавливать действия.

Как только вы определите, какой фрагмент является проблемой, вам нужно вернуться в свое приложение раньше и более внимательно посмотреть на типы данных, которые вы переводите в состояние сохранения в Fragment.onSaveInstanceState(). Надеюсь, это указывает на правильное направление.

Если это проблема proguard, вы должны увидеть, как ошибка исчезла, если вы отключите минификацию. И в этом случае вам может понадобиться правило proguard или аннотация @Keep для одного из ваших пользовательских типов Parcelable. Если ошибка происходит с минификацией и без нее, она, вероятно, не связана с Proguard.

  • 0
    Это определенно не ProGuard. Бывает и с отладочной сборкой тоже. Это проблема с Bundle, когда Android пытается восстановить сохраненное состояние экземпляра. Будем расследовать дальше как можно скорее.
0

Я только что узнал, что вы можете помешать своему тестовому устройству сохранять активность. В разделе "Разработчик" есть опция "Приложения", которая при включении уничтожает действия каждый раз, когда пользователь их покидает.

После включения этой опции я смог воспроизвести ошибку, просто закрыв и снова открыв свое приложение. Как вы сказали, это ошибка в методе onCreate(). В моем случае причина в ClassNotFoundException при отмене вызова настраиваемого Parcelable из моего сохраненного состояния экземпляра. Возможно, это не решение вашей проблемы, но, по крайней мере, может помочь вам воспроизвести и зафиксировать ошибку. Хорошей охоты!

  • 0
    эй @Richard R, спасибо. да - я использовал опцию «сохранить без действий», и да - это помогло мне иногда находить проблемы такого типа. Эта проблема обычно возникает из-за (a) некоторых объектов, которые можно передать, которые содержат вложенный объект, который НЕ реализовал Parcelable, или (b) пользовательских представлений, которые не восстанавливали данные должным образом. Проблема все еще в том, что этот метод - «выстрел в темноте». Я надеялся на какой-нибудь способ прочитать записанные данные. Я имею в виду - зачем упоминать '... код типа XXXX со смещением YYY', если эти цифры не соответствуют чему-либо полезному для отладки?
  • 0
    Да, вы правы, это вариант (b) в моем случае: я использую пользовательские представления и у меня была ошибка в одном из методов onRestoreInstanceState (). Мне потребовалось некоторое время, чтобы найти класс с ошибками, но, наконец, все решилось. Спасибо за подсказку @Mardann

Ещё вопросы

Сообщество Overcoder
Наверх
Меню