Search code examples
androidsavebundlestateparcelable

Error with reading parcelable object (after application is restored)


I have to save my custom class in save state bundle. So, I made it Parcelable and it looks good. When I rotate screen everything is goind well. But, when I minimalize my app, open some other, rotate screen and I try to go back to my app (from recent apps) it crashes.

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.game/com.example.game.MainActivity}: java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = com.example.game.Player)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2306)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2366)
        at android.app.ActivityThread.access$800(ActivityThread.java:149)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5297)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
 Caused by: java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = com.example.game.Player)
        at android.os.Parcel.readSerializable(Parcel.java:2378)
        at android.os.Parcel.readValue(Parcel.java:2197)
        at android.os.Parcel.readListInternal(Parcel.java:2520)
        at android.os.Parcel.readList(Parcel.java:1655)
        at com.example.game.Players.<init>(Players.java:106)
        at com.example.game.Players$1.createFromParcel(Players.java:96)
        at com.example.game.Players$1.createFromParcel(Players.java:93)
        at android.os.Parcel.readParcelable(Parcel.java:2246)
        at android.os.Parcel.readValue(Parcel.java:2146)
        at android.os.Parcel.readArrayMapInternal(Parcel.java:2479)
        at android.os.BaseBundle.unparcel(BaseBundle.java:221)
        at android.os.Bundle.getSparseParcelableArray(Bundle.java:871)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:831)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1049)
        at android.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:1864)
        at android.app.Activity.onCreate(Activity.java:949)
        at com.example.game.MainActivity.onCreate(MainActivity.java:24)
        at android.app.Activity.performCreate(Activity.java:6020)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2366)
            at android.app.ActivityThread.access$800(ActivityThread.java:149)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5297)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
 Caused by: java.lang.ClassNotFoundException: com.example.game.Player
        at java.lang.Class.classForName(Native Method)
        at java.lang.Class.forName(Class.java:308)
        at android.os.Parcel$2.resolveClass(Parcel.java:2364)
        at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1641)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:657)
        at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1782)
        at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:761)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)
        at android.os.Parcel.readSerializable(Parcel.java:2372)
            at android.os.Parcel.readValue(Parcel.java:2197)
            at android.os.Parcel.readListInternal(Parcel.java:2520)
            at android.os.Parcel.readList(Parcel.java:1655)
            at com.example.game.Players.<init>(Players.java:106)
            at com.example.game.Players$1.createFromParcel(Players.java:96)
            at com.example.game.Players$1.createFromParcel(Players.java:93)
            at android.os.Parcel.readParcelable(Parcel.java:2246)
            at android.os.Parcel.readValue(Parcel.java:2146)
            at android.os.Parcel.readArrayMapInternal(Parcel.java:2479)
            at android.os.BaseBundle.unparcel(BaseBundle.java:221)
            at android.os.Bundle.getSparseParcelableArray(Bundle.java:871)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:831)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1049)
            at android.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:1864)
            at android.app.Activity.onCreate(Activity.java:949)
            at com.example.game.MainActivity.onCreate(MainActivity.java:24)
            at android.app.Activity.performCreate(Activity.java:6020)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2366)
            at android.app.ActivityThread.access$800(ActivityThread.java:149)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5297)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
 Caused by: java.lang.ClassNotFoundException: com.example.game.Player
        at java.lang.Class.classForName(Native Method)
        at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
        at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
            at java.lang.Class.classForName(Native Method)
            at java.lang.Class.forName(Class.java:308)
            at android.os.Parcel$2.resolveClass(Parcel.java:2364)
            at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1641)
            at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:657)
            at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1782)
            at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:761)
            at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1983)
            at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1940)
            at android.os.Parcel.readSerializable(Parcel.java:2372)
            at android.os.Parcel.readValue(Parcel.java:2197)
            at android.os.Parcel.readListInternal(Parcel.java:2520)
at android.os.Parcel.readList(Parcel.java:1655)
            at com.example.game.Players.<init>(Players.java:106)
            at com.example.game.Players$1.createFromParcel(Players.java:96)
            at com.example.game.Players$1.createFromParcel(Players.java:93)
            at android.os.Parcel.readParcelable(Parcel.java:2246)
            at android.os.Parcel.readValue(Parcel.java:2146)
            at android.os.Parcel.readArrayMapInternal(Parcel.java:2479)
            at android.os.BaseBundle.unparcel(BaseBundle.java:221)
            at android.os.Bundle.getSparseParcelableArray(Bundle.java:871)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:831)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1049)
            at android.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:1864)
            at android.app.Activity.onCreate(Activity.java:949)
            at com.example.game.MainActivity.onCreate(MainActivity.java:24)
            at android.app.Activity.performCreate(Activity.java:6020)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2366)
            at android.app.ActivityThread.access$800(ActivityThread.java:149)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5297)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

So, players is parcelable class. It is basically a List. Player is another class, serializable.

Player.java

import java.io.Serializable;

public class Player implements Serializable{

private String name;
private int points = 0;

// getters and setters
}

Players.java

public class Players implements Parcelable {

    private List<Player> players;

    //constructor, getters, setters

@Override
public int describeContents() {

    return 0;

}

@Override
public void writeToParcel(Parcel parcel, int i) {

    parcel.writeList(players);

}

public static final Parcelable.Creator<Players> CREATOR = new Parcelable.Creator<Players>() {

    public Players createFromParcel(Parcel in) {
        return new Players(in);
    }

    public Players[] newArray(int size) {
        return new Players[size];
    }
};

public Players(Parcel in) {

    in.readList(players, List.class.getClassLoader());

}
}

At this point I don't know why my app crash. When I rotate it it's ok, when I minimize and maximize is ok, when I minimize, do some staff (open another app, rotate screen etc) and try to maximize it from recents it crash.

I'll be very gratefull for any kind of help ;) !

Have a good afternoon!


Solution

  • Parcelable class nest parcelable objects only.

    Here in your case Player is not parcelable and is used in Parcelable class Players. Try to implement Parcelable in Player class too.

    Your problem with minimising and opening the application is because Parcelable object is saved but it is not retrieved properly.

    try to make following changes in your code :

    public class Player implements Parcelable{
    
    String name;
    int points;
    
    // getter setter
    
    public static final Creator<Player> CREATOR = new Parcelable.Creator<Player>() {
        @Override
        public Player createFromParcel(Parcel in) {
            return new Player(in);
        }
    
        @Override
        public Player[] newArray(int size) {
            return new Player[size];
        }
    };
    
    public Player(Parcel in) {
        this.name = in.readString();
        this.points = in.readInt();
    }
    
    @Override
    public int describeContents() {
        return 0;
    }
    
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(points);
    }
    }
    

    And in Players class while reading the list replace:

    in.readList(players, List.class.getClassLoader());
    

    with :

    players = new ArrayList<>();
    in.readList(players, getClass().getClassLoader());
    

    Your code should work fine after these changes.