Jakub Holovsky Jakub Holovsky - 1 month ago 16
C# Question

Xamarin Android - Unable to start activity ComponentInfo{[activityName]}: java.lang.RuntimeException: Parcel android.os.Parcel@[address]

Recently, we have been getting a few of following exceptions in our app:


java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.myapp.android/com.myapp.android.WelcomeActivity}:
java.lang.RuntimeException: Parcel android.os.Parcel@426f0118:
Unmarshalling unknown type code 2131558952 at offset 736 at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2429)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2493)
at android.app.ActivityThread.access$800(ActivityThread.java:166) at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1283)
at android.os.Handler.dispatchMessage(Handler.java:102) at
android.os.Looper.loop(Looper.java:136) at
android.app.ActivityThread.main(ActivityThread.java:5584) at
java.lang.reflect.Method.invokeNative(Native Method) at
java.lang.reflect.Method.invoke(Method.java:515) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) at
dalvik.system.NativeStart.main(Native Method) Caused by:
java.lang.RuntimeException: Parcel android.os.Parcel@426f0118:
Unmarshalling unknown type code 2131558952 at offset 736 at
android.os.Parcel.readValue(Parcel.java:2087) at
android.os.Parcel.readSparseArrayInternal(Parcel.java:2382) at
android.os.Parcel.readSparseArray(Parcel.java:1742) at
android.os.Parcel.readValue(Parcel.java:2077) at
android.os.Parcel.readArrayMapInternal(Parcel.java:2321) at
android.os.Bundle.unparcel(Bundle.java:249) at
android.os.Bundle.getSparseParcelableArray(Bundle.java:1273) at
com.android.internal.policy.impl.PhoneWindow.restoreHierarchyState(PhoneWindow.java:1884)
at android.app.Activity.onRestoreInstanceState(Activity.java:989) at
android.app.Activity.performRestoreInstanceState(Activity.java:961)
at
android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1145)

at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2407)
... 11 more


I checked my activity but there is nothing related to Parcelable stuff. So I dug more and found Parcelable code in one of our widgets that is being used in the activity. I have very high suspicion that it might be caused by the following code:

protected override void OnRestoreInstanceState(IParcelable state)
{
try
{
SavedState savedState = (SavedState)state;
base.OnRestoreInstanceState(savedState.SuperState);
mCurrentPage = savedState.CurrentPage;
mSnapPage = savedState.CurrentPage;
}
catch
{
base.OnRestoreInstanceState(state);
// Ignore, this needs to support IParcelable...
}
RequestLayout();
}

protected override IParcelable OnSaveInstanceState()
{
var superState = base.OnSaveInstanceState();
var savedState = new SavedState(superState)
{
CurrentPage = mCurrentPage
};
return savedState;
}

private class SavedState : BaseSavedState
{
public int CurrentPage { get; set; }

public SavedState(IParcelable superState) : base(superState)
{
}

private SavedState(Parcel parcel) : base(parcel)
{
CurrentPage = parcel.ReadInt();
}

public override void WriteToParcel(Parcel dest, ParcelableWriteFlags flags)
{
base.WriteToParcel(dest, flags);
dest.WriteInt(CurrentPage);
}

[ExportField("CREATOR")]
private static SavedStateCreator InitializeCreator()
{
return new SavedStateCreator();
}

private class SavedStateCreator : Java.Lang.Object, IParcelableCreator
{
public Java.Lang.Object CreateFromParcel(Parcel source)
{
return new SavedState(source);
}

public Java.Lang.Object[] NewArray(int size)
{
return new Object[size];
}
}
}


The code was actually taken from this example in here:
https://github.com/xamarin/monodroid-samples/blob/master/ViewPagerIndicator/ViewPagerIndicator/Library/CirclePageIndicator.cs

I have been personally unable to reproduce this but it has come out in crash reporting for our app.

Any tips on this would be appreciated.

Answer

Fixed by removing all the creator stuff and sticking with the basics:

protected override void OnRestoreInstanceState(IParcelable state)
        {
            var bundle = state as Bundle;
            if (bundle != null)
            {
                mCurrentPage = bundle.GetInt("currentPage", 0);
                mSnapPage = mCurrentPage;
                state = (IParcelable)bundle.GetParcelable("superState");
            }
            base.OnRestoreInstanceState(state);
            RequestLayout();
        }

        protected override IParcelable OnSaveInstanceState()
        {
            var bundle = new Bundle();
            bundle.PutParcelable("superState", base.OnSaveInstanceState());
            bundle.PutInt("currentPage", mCurrentPage);
            return bundle;
        }
Comments