BadParcelableException - BroadcastReceiver intent crash

2.6k Views Asked by At

This error seems to happen sporadically, which is odd. It usually works fine, but occasionally it creeps up. Here is my code, which is in a BroadcastReceiver:

public void onReceive(Context context, Intent intent) {
    MyCustomResponseMsg message = new MyCustomResponseMsg((MyMessage) intent.getParcelableExtra(MyMessage.EXTRA_MESSAGE_KEY));

    // do stuff with the message

    setResultCode(Activity.RESULT_OK);
}

And here is the exception:

01-16 10:05:03.834: ERROR/AndroidRuntime(13533): FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start receiver com.(path-to-broadcast-receiver).MyReqReceiver:   
android.os.BadParcelableException: ClassNotFoundException when unmarshalling:  com.(path-to-my-message).MyMessage
at android.app.ActivityThread.handleReceiver(ActivityThread.java:1805)
at android.app.ActivityThread.access$2400(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:981)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling:     com.(path-to-my-message).MyMessage
at android.os.Parcel.readParcelable(Parcel.java:1958)
at android.os.Parcel.readValue(Parcel.java:1846)
at android.os.Parcel.readMapInternal(Parcel.java:2083)
at android.os.Bundle.unparcel(Bundle.java:208)
at android.os.Bundle.getParcelable(Bundle.java:1100)
at android.content.Intent.getParcelableExtra(Intent.java:3437)
at     com.(path).MyReceiver.onReceive(My    ReqReceiver.java:23)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:1794)
... 10 more

The error seems to occur on the getParcelableExtra line. The "MyMessage" class (obviously named something different in my own project) does indeed exist; it's contained in an library. It works most of the time, but there are times when I can get this to crash every time the broadcast is received.

I realize this isn't much to go off of, but I just wanted to see if there's anything I could be doing differently in the receiver to capture this so that it doesn't cause a crash. Or if it's definitely something on the side of sending the Broadcast, then I can focus on that if needed. But in the interim, I just wanted to make sure this was setup properly for my purposes. I've checked other similar posts with this crash, but I can't seem to find any that involve this specific kind of parcelable getting from the intent in a BroadcastReceiver.

Thanks in advance for any guidance on this!

EDIT Here is what the constructor for MyMessage looks like, if needed:

public MyMessage(Parcel in) {
    field1 = in.readInt();
    field2 = in.readString();
    field3 = in.readString();
}
1

There are 1 best solutions below

3
On BEST ANSWER

Most of the cases of this issue I've seen were resolved by setting the correct ClassLoader in process of unmarshalling your custom Parcelable class.

Have a closer look at your MyMessage constructor, specifically on how you obtain ClassLoader:

private MyMessage(Parcel in) {
    //...
    //causes ClassNotFoundException
    this.field=in.readParcelable(null); 
    //causes ClassNotFoundException, in fact it's equivalent to previous
    this.field=in.readParcelable(ClassLoader.getSystemClassLoader()); 

    //this one should work
    this.field=in.readParcelable(getClass().getClassLoader());
}

More details can be found in this question.


UPDATE: Also, try setting correct ClassLoader for Bundle contained in your Intent:

public void onReceive(Context context, Intent intent) {
    Bundle extras=intent.getExtras();
    extras.setClassLoader(getClass().getClassLoader());
    MyCustomResponseMsg message = new MyCustomResponseMsg((MyMessage) extras.getParcelable(MyMessage.EXTRA_MESSAGE_KEY));
    //...
}