0

I have an object with a couple of Strings, one int and another object which has 4 inner objects. All of them implementing Parcelable. In order to generate the boilerplate code, I used Parcelable plugin from Android studio.

Even though all the objects are parcelable, I'm getting the following error: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: AlbumTrackResponse

Here's how the POJOs look like:

Main object:

public class AlbumTrackResponse implements Parcelable {

private String id;
private String albumId;
private String position;
private String title;
private int rate;
private AllServices services;

public AllServices getServices() {
    return services;
}

public void setServices(AllServices services) {
    this.services = services;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getAlbumId() {
    return albumId;
}

public void setAlbumId(String albumId) {
    this.albumId = albumId;
}

public String getPosition() {
    return position;
}

public void setPosition(String position) {
    this.position = position;
}

public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}

public int getRate() {
    return rate;
}

public void setRate(int rate) {
    this.rate = rate;
}


protected AlbumTrackResponse(Parcel in) {
    id = in.readString();
    albumId = in.readString();
    position = in.readString();
    title = in.readString();
    rate = in.readInt();
    services = (AllServices) in.readValue(AllServices.class.getClassLoader());
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(id);
    dest.writeString(albumId);
    dest.writeString(position);
    dest.writeString(title);
    dest.writeInt(rate);
    dest.writeValue(services);
}

@SuppressWarnings("unused")
public static final Parcelable.Creator<AlbumTrackResponse> CREATOR = new Parcelable.Creator<AlbumTrackResponse>() {
    @Override
    public AlbumTrackResponse createFromParcel(Parcel in) {
        return new AlbumTrackResponse(in);
    }

    @Override
    public AlbumTrackResponse[] newArray(int size) {
        return new AlbumTrackResponse[size];
    }
};

}

Inner object with 4 objects

public class AllServices implements Parcelable {

private GigRevService gigrev;
private AppleService apple;
private GoogleService google;
private SpotifyService spotify;

protected AllServices(Parcel in) {
    gigrev = (GigRevService) in.readValue(GigRevService.class.getClassLoader());
    apple = (AppleService) in.readValue(AppleService.class.getClassLoader());
    google = (GoogleService) in.readValue(GoogleService.class.getClassLoader());
    spotify = (SpotifyService) in.readValue(SpotifyService.class.getClassLoader());
}

@Override
public int describeContents() {
    return 0;
}

public GigRevService getGigrev() {
    return gigrev;
}

public void setGigrev(GigRevService gigrev) {
    this.gigrev = gigrev;
}

public AppleService getApple() {
    return apple;
}

public void setApple(AppleService apple) {
    this.apple = apple;
}

public GoogleService getGoogle() {
    return google;
}

public void setGoogle(GoogleService google) {
    this.google = google;
}

public SpotifyService getSpotify() {
    return spotify;
}

public void setSpotify(SpotifyService spotify) {
    this.spotify = spotify;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeValue(gigrev);
    dest.writeValue(apple);
    dest.writeValue(google);
    dest.writeValue(spotify);

}

@SuppressWarnings("unused")
public static final Parcelable.Creator<AllServices> CREATOR = new Parcelable.Creator<AllServices>() {
    @Override
    public AllServices createFromParcel(Parcel in) {
        return new AllServices(in);
    }

    @Override
    public AllServices[] newArray(int size) {
        return new AllServices[size];
    }
};

}

The inner objects from here contain just string items.

Here's how I pass the ArrayList to the bundle:

    bundle.putParcelableArrayList(MediaPlayerService.TRACK_LIST, trackList);

I'm passing the items from an Activity to a Service. Any ideas why I'm getting this error?

EDIT: Implementation of service classes

public class GoogleService implements Parcelable {

private String name;
private String uri;

public String getUri() {
    return uri;
}

public void setUri(String uri) {
    this.uri = uri;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

protected GoogleService(Parcel in) {
    name = in.readString();
    uri = in.readString();
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeString(uri);
}

@SuppressWarnings("unused")
public static final Parcelable.Creator<GoogleService> CREATOR = new Parcelable.Creator<GoogleService>() {
    @Override
    public GoogleService createFromParcel(Parcel in) {
        return new GoogleService(in);
    }

    @Override
    public GoogleService[] newArray(int size) {
        return new GoogleService[size];
    }
};

}

funkycookie
  • 226
  • 2
  • 16

2 Answers2

0

This looks extremly strange

this.services = in.readParcelable(getClass().getClassLoader());

You are pointing out to the wrong class loader. You have to use it like this

this.services = (AllServices)in.readParcelable(AllServices.class.getClassLoader());

Besides that, I am always using this site http://www.parcelabler.com/ to quickly generate my Parceables. Or you could use it like this

services = (AllServices) in.readValue(AllServices.class.getClassLoader());
Murat Karagöz
  • 35,401
  • 16
  • 78
  • 107
0

Here:

protected AllServices(Parcel in) { this.gigrev = in.readParcelable(getClass().getClassLoader()); 
this.apple = in.readParcelable(getClass().getClassLoader()); 
this.google = in.readParcelable(getClass().getClassLoader()); 
this.spotify = in.readParcelable(getClass().getClassLoader()); }

Replace it with

protected AllServices(Parcel in) { this.gigrev = in.readParcelable(GigRevService.class.getClassLoader()); 
this.apple = in.readParcelable(AppleService.class.getClassLoader()); 
this.google = in.readParcelable(GoogleService.class.getClassLoader()); 
this.spotify = in.readParcelable(SpotifyService.class.getClassLoader()); }

And replace:

 this.services = in.readParcelable(getClass().getClassLoader());

With:

this.services = in.readParcelable(AllServices.class.getClassLoader());

Also can you show the GoogleService etc classes? Each inner object's class must have a Parcelable creator also and implement the Parcelable interface as well.

mantlabs
  • 352
  • 2
  • 6
  • I changed all class loaders accordingly, I get the same error. – funkycookie Sep 27 '16 at 14:07
  • 1
    Did you implement also the Parcelable interface on GoogleService AppleService etc? – mantlabs Sep 27 '16 at 14:08
  • Yes, I used the website from above to recreate everything, on all objects – funkycookie Sep 27 '16 at 14:08
  • Can you show the Parcelable implementation of those classes? I always write Parcelables by hand, without using any website. – mantlabs Sep 27 '16 at 14:10
  • I edited the question and added an example of one of the services, the rest of them look alike. – funkycookie Sep 27 '16 at 14:14
  • Try the following: Check the order of the member variables in each class that implements the Parcelable. The variables order and the read and write from/to the Parcelable must be the same. And also, try Build->Clean Project and Build it and run it again (no instant run) – mantlabs Sep 27 '16 at 14:28
  • Please update your question with the correct code with the fixes suggested here, so that we know what exactly you have written and where we should focus our attention. As I see you have SuppressWarnings unused, which means that you may have not called getClassLoader for that class and you decided to cease the "unused" warning this way. – mantlabs Sep 27 '16 at 14:38
  • I updated my question with solutions from the post and it's still not working. I can remove the annotation, it was put in there by the generator. Forgot to specify, most of the classes are in a different module. But that should not represent a problem, shouldn't it? – funkycookie Sep 28 '16 at 06:18