添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
重情义的冲锋衣  ·  java - How to resolve ...·  1 年前    · 
挂过科的企鹅  ·  flutter ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Android 10 BadParcelableException ClassNotFoundException when unmarshalling using Kotlin @Parcelize

Ask Question

In Firebase, I'm getting various crashes in my production app (uses Dexguard), while using Parcelable .

These crashes are now affecting almost 200 users and are grouped into 3 entries on Firebase.

In one entry, crashes are only on Samsung devices, in another, are only Xiaomi devices and in the other, are more brands but 81% are from HMD Global.

ALL these devices are running Android 10 so this might be a problem with this OS version. I can see that the crashes are contained to 5 or 6 custom objects. Other than that, some crashes are related to:

Fatal Exception: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: androidx.fragment.app.FragmentManagerState
   at android.os.Parcel.readParcelableCreator(Parcel.java:3059)
   at android.os.Parcel.readParcelable(Parcel.java:2981)
   at android.os.Parcel.readValue(Parcel.java:2883)
   at android.os.Parcel.readArrayMapInternal(Parcel.java:3261)
   at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:292)
   at android.os.BaseBundle.unparcel(BaseBundle.java:236)
   at android.os.BaseBundle.size(BaseBundle.java:355)
   at android.app.servertransaction.LaunchActivityItem.hashCode(LaunchActivityItem.java:208)
   at java.util.AbstractList.hashCode(AbstractList.java:541)
   at java.util.Objects.hashCode(Objects.java:98)
   at android.app.servertransaction.ClientTransaction.hashCode(ClientTransaction.java:241)
   at android.app.servertransaction.TransactionExecutorHelper.tId(TransactionExecutorHelper.java:266)
   at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:86)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2220)
   at android.os.Handler.dispatchMessage(Handler.java:107)
   at android.os.Looper.loop(Looper.java:237)
   at android.app.ActivityThread.main(ActivityThread.java:8019)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

In one of my custom objects, I'm having this type of crash (for my other custom objects, the crash is the same).

Fatal Exception: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.mypackagename.InfoData
       at android.os.Parcel.readParcelableCreator(Parcel.java:3059)
       at android.os.Parcel.readParcelable(Parcel.java:2981)
       at android.os.Parcel.readValue(Parcel.java:2883)
       at android.os.Parcel.readArrayMapInternal(Parcel.java:3261)
       at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:292)
       at android.os.BaseBundle.unparcel(BaseBundle.java:236)
       at android.os.BaseBundle.size(BaseBundle.java:355)
       at android.app.servertransaction.LaunchActivityItem.hashCode(LaunchActivityItem.java:208)
       at java.util.AbstractList.hashCode(AbstractList.java:541)
       at java.util.Objects.hashCode(Objects.java:98)
       at android.app.servertransaction.ClientTransaction.hashCode(ClientTransaction.java:241)
       at android.app.servertransaction.TransactionExecutorHelper.tId(TransactionExecutorHelper.java:266)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:86)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2220)
       at android.os.Handler.dispatchMessage(Handler.java:107)
       at android.os.Looper.loop(Looper.java:237)
       at android.app.ActivityThread.main(ActivityThread.java:8019)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

As an example, here is an example of the models that I'm having crashes.

@Parcelize
class NumberDetails(internal var numbers: ArrayList<String> = arrayListOf(), var userState: UserState = UserState.INACTIVE) : Parcelable {
    fun clear() = numbers.clear()
    fun getNumbers(): String = numbers.joinToString("")

Another:

@Parcelize
data class InfoData(var needsCheck: Boolean = false, var amount: Double = 0.0, var fee: Double? = null) : Parcelable

And another:

abstract class Screen(open val identifier: String = "") : Parcelable {
    @Parcelize
    data class ActivateScreen(override val identifier: String) : Screen()
   //More entries like above

The first example is an inner class while the second is declared in a file where I already have other stuff (don't know if this matters)

I'm unable to replicate the crash on any of my devices. Any idea why I'm having these crashes only on Android 10 devices?

UPDATE:

While trying to fix a crash that my app had, I was able to reproduce the FragmentManagerState crash, that is, my app crashed and then it crashed again with the FragmentManagerState crash. Although I can replicate my app crash always, the subsequent crash I was only to replicate it ONCE.

This was replicated in an Emulator running Android 10 and with Don't Keep Activities enabled. My app crash only happened due to the Don't Keep Activities enabled (in the markets that I work on, this is common scenario due to low-end devices)

In my app, I can have the following steps:

ActivityA -> ActivityB -> ActivityC -> ActivityD (PdfViewer) -> PickActivity (I/ActivityTaskManager: START u0 {act=android.intent.action.CREATE_DOCUMENT cat=[android.intent.category.OPENABLE] typ=application/pdf cmp=com.android.documentsui/.picker.PickActivity)

In ActivityD, a place where I can preview a PDF, I can click on a button to save the PDF in storage. That click on the button opens the system PickActivity. When I save the PDF and control is passed to ActivityC, my app crashes (only with DNKA enabled) since I'm not properly handling onSavedInstanceState.

From the logs (removed unnecessary stuff here) I can see:

I/ActivityTaskManager: START u0 {act=android.intent.action.CREATE_DOCUMENT cat=[android.intent.category.OPENABLE] typ=application/pdf cmp=com.android.documentsui/.picker.PickActivity (has extras)} from uid 10219
I/ActivityManager: Start proc 9418:com.android.documentsui/u0a50 for activity {com.android.documentsui/com.android.documentsui.picker.PickActivity}
I/ActivityManager: Start proc 9443:com.android.externalstorage/u0a56 for content provider {com.android.externalstorage/com.android.externalstorage.ExternalStorageProvider}
I/ActivityTaskManager: Displayed com.android.documentsui/.picker.PickActivity: +1s133ms
2016-3548/? I/ActivityTaskManager: START u0 {cmp=com.myapp.packagename/com.myapp.package.ActivityC} from uid 10219
2016-2323/? I/ActivityTaskManager: START u0 {cmp=com.myapp.packagename/com.myapp.package.ActivityC} from uid 10219

Then my app crashes due to the lack of proper handling of saved instance state

W/ActivityTaskManager: Activity top resumed state loss timeout for ActivityRecord{bdaedc1 u0 com.myapp.packagename/com.myapp.package.ActivityD t1250}
W/ActivityTaskManager: Activity pause timeout for ActivityRecord{bdaedc1 u0 com.myapp.packagename/com.myapp.package.ActivityD t1250}
W/ActivityTaskManager:   Force finishing activity com.myapp.packagename/com.myapp.package.ActivityC
W/ActivityTaskManager:   Force finishing activity com.myapp.packagename/com.myapp.package.ActivityC
I/ActivityManager: Process com.myapp.packagename (pid 8990) has died: fore TOP 
W/ActivityTaskManager: Force removing ActivityRecord{4b658e u0 com.myapp.packagename/com.myapp.package.ActivityB t1250}: app died, no saved state
W/ActivityTaskManager: Force removing ActivityRecord{210b4e5 u0 com.myapp.packagename/com.myapp.package.Activitya t1250}: app died, no saved state
I/ActivityManager: Start proc 9609:com.myapp.packagename/u0a219 for activity {com.myapp.packagename/com.myapp.package.ActivityD}
W/ActivityTaskManager: Activity top resumed state loss timeout for ActivityRecord{5d7ded3 u0 com.myapp.packagename/com.myapp.package.ActivityC t-1 f}

I now can see by the logs that my app is launched (logs from my application class)

I/ActivityTaskManager: START u0 {flg=0x10008000 cmp=com.myapp.packagename/com.myapp.package.SplashActivity} from uid 10219
I/ActivityTaskManager: START u0 {cmp=com.myapp.packagename/com.myapp.package.SplashActivity} from uid 10219
 W/ActivityTaskManager: startActivity called from finishing ActivityRecord{bdaedc1 u0 com.myapp.packagename/com.myapp.package.ActivityD t1250 f}; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { cmp=com.myapp.packagename/com.myapp.package.SplashActivity }
W/ActivityTaskManager: Duplicate finish request for ActivityRecord{bdaedc1 u0 com.myapp.packagename/com.myapp.package.ActivityD t1250 f}
W/ActivityTaskManager: Duplicate finish request for ActivityRecord{685f9ab u0 com.myapp.packagename/com.myapp.package.ActivityC t1250 f}
W/ActivityTaskManager: Activity top resumed state loss timeout for ActivityRecord{bdaedc1 u0 com.myapp.packagename/com.myapp.package.ActivityD t1250 f}
W/ActivityTaskManager: Activity pause timeout for ActivityRecord{bdaedc1 u0 com.myapp.packagename/com.myapp.package.ActivityD t1250 f}

And then:

9609-9609/com.myapp.packagename E/Parcel: Class not found when unmarshalling: androidx.fragment.app.FragmentManagerState
    java.lang.ClassNotFoundException: androidx.fragment.app.FragmentManagerState

While analyzing the logs I could see that one of my activities was appearing twice. I managed to reproduce that with fast multiple clicking on the button that launches that activity. I then tried to replicate it. Restarted the flow, double-clicked the button, tried to save the PDF, and after the app crash, I could see the FragmentManagerState crash. I was able to reproduce this only once.

1 - Since all my crashes are related to BadParcelableException (ones from FragmentManagerState and others from other things), and with the above mentioned in mind, could the crashes that I'm seeing on the play store be marked as BadParcelableException but are crashes related to other things in my app, that also triggers the BadParcelableException crashes and PlayStore and Firebase only show the later ones? 2 - Any suggestion on what could I improve to properly log the crashes in my app?

You might want to expand your minimal reproducible example to show the full stack trace for each place that is generating crashes. In general, custom Parcelable objects are risky in some circumstances. – CommonsWare Jan 31, 2021 at 16:50 @CommonsWare Thanks. I cannot reproduce the error but edited the question with two stack traces. So, looking at your post, do you recommend the workaround from Matthias Urhahn and do the technique suggested by the SO answer? If so, I would need to do a bit of refactoring/replacement on my end but it's better than crashes. – Favolas Jan 31, 2021 at 18:29

This problem was reported a year ago for your first stack trace, the one referring to FragmentManagerState. It seems to be tied to an Android 10-specific bug.

For your InfoState crash, putting the object into the bundle as a byte[] should clear up the problem. That is not an option for you with FragmentManagerState, though, as that is being done deeper in the Jetpack.

You might want to confirm that you are on the latest androidx.fragment and androidx.activity libraries, in case they added a workaround. Otherwise, you might review the comments on that issue, as some developers reported some solutions, but they are rather specific and may or may not relate to your scenario.

@Favolas: I probably wrote those solutions in the wrong order. Look at the issue and see if any of the scenarios described there (e.g., having recently removed singleTop) match your case. If so, that fix may be sufficient. Keeping up to date with the dependencies is a fairly standard thing. Converting your InfoState into byte[] may help, but it's possible that the other solutions will clear matters up without having to go this route. – CommonsWare Jan 31, 2021 at 18:55 Hello. Still having the crashes but found something. Can you please check my update and see if somehow it makes sense? Thanks. – Favolas Mar 7, 2021 at 9:52

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.