Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How (and where) to fix android.os.BadParcelableException: ClassNotFoundException when unmarshalling: RecyclerView$SavedState?

I have been getting below exception in my android app's production apk for 1 day now:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.a.b/com.a.b.c.d.HomeActivity}: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.v7.widget.RecyclerView$SavedState
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1654)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1670)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3695)
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:878)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.v7.widget.RecyclerView$SavedState
at android.os.Parcel.readParcelable(Parcel.java:1958)
at android.os.Parcel.readValue(Parcel.java:1846)
at android.os.Parcel.readSparseArrayInternal(Parcel.java:2112)
at android.os.Parcel.readSparseArray(Parcel.java:1568)
at android.os.Parcel.readValue(Parcel.java:1903)
at android.os.Parcel.readMapInternal(Parcel.java:2083)
at android.os.Bundle.unparcel(Bundle.java:208)
at android.os.Bundle.getSparseParcelableArray(Bundle.java:1167)
at android.support.design.internal.NavigationMenuPresenter.onRestoreInstanceState(Unknown Source)
at android.support.v7.view.menu.i.dispatchRestoreInstanceState(Unknown Source)
at android.support.v7.view.menu.i.restorePresenterStates(Unknown Source)
at android.support.design.widget.NavigationView.onRestoreInstanceState(Unknown Source)
at android.view.View.dispatchRestoreInstanceState(View.java:6287)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:1211)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:1215)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:1215)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:1215)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:1215)
at android.view.View.restoreHierarchyState(View.java:6266)
at com.android.internal.policy.impl.PhoneWindow.restoreHierarchyState(PhoneWindow.java:1506)
at android.app.Activity.onRestoreInstanceState(Activity.java:847)
at android.app.Activity.performRestoreInstanceState(Activity.java:819)
at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1096)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1632)
... 11 more

All the above crash reports are from Android 2.3.3 - 2.3.7 versions. Not sure what is causing this.

I searched other similar posts too but the answers were around a custom object that implements parcelable which I do not implement in my app.

I am using the latest version of android support library and play-services in my app as given below:

compile 'com.android.support:cardview-v7:23.1.1'
compile 'com.android.support:design:23.1.1'

compile 'com.google.android.gms:play-services-analytics:8.4.0'
compile 'com.google.android.gms:play-services-ads:8.4.0'
compile 'com.google.android.gms:play-services-appinvite:8.4.0'
compile 'com.google.android.gms:play-services-plus:8.4.0'

Here is the code (that I feel relevant, if not please let me know what else is needed) from the activity that is failing:

private void initNavigationMenu() {
    mNavigationView = (NavigationView) findViewById(R.id.nav_view);
    mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem) {
            return onNavItemSelected(menuItem);
        }
    });

    Menu menu = mNavigationView.getMenu();

    MenuItem menuItem = menu.findItem(R.id.action_tutorial);
    IconDrawable iconDrawable = new IconDrawable(this, MaterialIcons.md_ondemand_video)
            .colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_settings);
    iconDrawable = new IconDrawable(this, MaterialIcons.md_settings).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_images_all);
    iconDrawable = new IconDrawable(this, EntypoIcons.entypo_images).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_images_screenshots);
    iconDrawable = new IconDrawable(this, MaterialIcons.md_camera).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_favorites);
    iconDrawable = new IconDrawable(this, MaterialIcons.md_favorite).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_translate);
    iconDrawable = new IconDrawable(this, MaterialIcons.md_translate).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_feedback);
    iconDrawable = new IconDrawable(this, MaterialIcons.md_feedback).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_rate);
    iconDrawable = new IconDrawable(this, MaterialIcons.md_rate_review).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_invite);
    iconDrawable = new IconDrawable(this, MaterialIcons.md_insert_invitation).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_facebook);
    iconDrawable = new IconDrawable(this, FontAwesomeIcons.fa_facebook).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_twitter);
    iconDrawable = new IconDrawable(this, FontAwesomeIcons.fa_twitter).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_google_plus);
    iconDrawable = new IconDrawable(this, FontAwesomeIcons.fa_google_plus).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);

    menuItem = menu.findItem(R.id.action_remove_ads);
    iconDrawable = new IconDrawable(this, MaterialIcons.md_attach_money).colorRes(R.color.black);
    menuItem.setIcon(iconDrawable);
    menuItem.setVisible(!BuildConfig.IS_PRO);

    setHeaderView();
}

private void setHeaderView() {

    boolean initializePlusOneButton = false;
    GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
    int code = googleApiAvailability.isGooglePlayServicesAvailable(this);
    if (code == ConnectionResult.SUCCESS) {
        initializePlusOneButton = true;
    } else if (googleApiAvailability.isUserResolvableError(code)) {
        googleApiAvailability.showErrorDialogFragment(this, code, REQ_CODE_GOOGLE_API_ERROR);
    }

    View headerView = LayoutInflater.from(this).inflate(
            initializePlusOneButton ?
                    R.layout.activity_home_drawer_header :
                    R.layout.activity_home_drawer_header_wo_plus_button, null);
    if (initializePlusOneButton) {
        mPlusOneButton = (PlusOneButton) headerView.findViewById(R.id.plus_one_button);
    }

    mNavigationView.addHeaderView(headerView);

    gLogger.debug(String.format(
            "setHeaderView(): initialize plusOneButton=%s", initializePlusOneButton
    ));
}

Contents of R.layout.activity_home_drawer_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="?attr/colorPrimary"
android:orientation="vertical">

<com.andexert.library.RippleView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="bottom"
    android:padding="10dp"
    app:rv_rippleDuration="300"
    app:rv_type="rectangle">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <com.joanzapata.iconify.widget.IconTextView
            android:layout_width="60dp"
            android:layout_height="match_parent"
            android:layout_above="@+id/app_name"
            android:layout_gravity="center_vertical"
            android:gravity="center"
            android:text="{md-camera}"
            android:textColor="@color/white"
            android:textSize="50sp" />

        <LinearLayout
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:orientation="vertical"
            android:padding="10dp">

            <TextView
                android:id="@+id/app_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_marginBottom="10dp"
                android:layout_marginTop="5dp"
                android:text="@string/app_name"
                android:textColor="@color/white"
                android:textSize="16sp"
                android:textStyle="italic|bold" />

            <com.google.android.gms.plus.PlusOneButton
                xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus"
                android:id="@+id/plus_one_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                plus:annotation="bubble"
                plus:size="medium" />
        </LinearLayout>
    </LinearLayout>
</com.andexert.library.RippleView>

</LinearLayout>

Contents of R.layout.activity_home_drawer_header_wo_plus_button.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="?attr/colorPrimary"
android:orientation="vertical">

<com.andexert.library.RippleView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="bottom"
    android:padding="10dp"
    app:rv_rippleDuration="300"
    app:rv_type="rectangle">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.joanzapata.iconify.widget.IconTextView
            android:layout_width="wrap_content"
            android:padding="10dp"
            android:layout_above="@+id/app_name"
            android:layout_weight="1"
            android:layout_gravity="center"
            android:gravity="center"
            android:layout_height="0dip"
            android:text="{md-camera}"
            android:textColor="@color/white"
            android:textSize="80sp" />

        <TextView
            android:id="@+id/app_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="10dp"
            android:text="@string/app_name"
            android:textColor="@color/white"
            android:textSize="18sp"
            android:textStyle="italic|bold" />
    </LinearLayout>
</com.andexert.library.RippleView>

</LinearLayout>
like image 370
Ankit Batra Avatar asked Dec 26 '15 09:12

Ankit Batra


2 Answers

Whichever View gives error, use android:saveEnabled="false" on xml declaration of that View or yourView.setSaveEnabled(false) programmatically. This way you avoid saving state of that View (when Application process is killed) and no crash at restore time.

like image 155
Jemshit Iskenderov Avatar answered Oct 21 '22 13:10

Jemshit Iskenderov


Opened up a ticket at bugs.google.com and for API 11+ it's fixed in Support library 24.0.0. For API <= 10 it will be fixed in a future release.

like image 38
Henrique de Sousa Avatar answered Oct 21 '22 11:10

Henrique de Sousa