Android Intent Parcelable: Class not found when unmarshalling - android

I looked all answers to question "Class not found when unmarshalling" in the Stackoverflow, but I don't found solution to my situation. I tried any variants but didn't work.
I get following error:
Here my Classes:
Class one:
public class Class1 implements Parcelable, Serializable {
private static final long serialVersionUID = -3892107077759983950L;
private long id;
private ArrayList<Class2> details;
public Class1(long id, ArrayList<Class2> details) {
this.id = id;
this.details = details;
}
public Class1(Parcel in) {
this.id = in.readLong();
details = new ArrayList<Class2>((Collection<? extends Class2>) Arrays.asList(in.readParcelableArray(Class2.class.getClassLoader())));
// details = (ArrayList<OrderDetail>)in.readSerializable();
// details = in.readArrayList(Class2.class.getClassLoader());
// in.readList(details, Class2.class.getClassLoader());
// in.readTypedList(details, Class2.CREATOR);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
// dest.writeSerializable(details);
// dest.writeList(details);
// dest.writeTypedList(details);
dest.writeParcelableArray(ordDetailListToArr(), flags);
}
#Override
public int describeContents() { return 0; }
public static final Parcelable.Creator<Class1> CREATOR
= new Parcelable.Creator<Class1>() {
public Class1 createFromParcel(Parcel in) {
return new Class1(in);
}
public Class1[] newArray(int size) {
return new Class1[size];
}
};
}
Class second:
public class Class2 implements Parcelable, Serializable {
private static final long serialVersionUID = 3242734374178052427L;
private long orderId;
private Class3 Class3;
public Class2(long orderId, Class3 Class3) {
this.orderId = orderId;
this.Class3 = Class3;
}
private Class2(Parcel in) {
this.orderId = in.readLong();
this.Class3 = (Class3) in.readParcelable(Class3.class.getClassLoader());
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(orderId);
dest.writeParcelable(Class3, flags);
}
#Override
public int describeContents() { return 0;}
public static final Parcelable.Creator<Class2> CREATOR
= new Parcelable.Creator<Class2>() {
public Class2 createFromParcel(Parcel in) {
return new Class2(in);
}
public Class2[] newArray(int size) {
return new Class2[size];
}
};
}
Class third:
public class Class3 extends Class4 implements Cloneable, Serializable {
private static final long serialVersionUID = 8712386538880552241L;
private int count;
public Class3(Class4 Class4, int count) {
super(Class4.getId(), Class4.getName());
this.count = count;
}
private Class3(Parcel in) {
super(in);
this.count = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(count);
}
#Override
public int describeContents() { return 0;}
public static final Parcelable.Creator<Class3> CREATOR
= new Parcelable.Creator<Class3>() {
public Class3 createFromParcel(Parcel in) {
return new Class3(in);
}
public Class3[] newArray(int size) {
return new Class3[size];
}
};
}
class fourth:
public class Class4 implements Parcelable, Serializable {
private static final long serialVersionUID = -8394588748958519736L;
private long id;
private String name;
public Class4(long id, String name) {
this.id = id;
this.name = name;
}
public Class4(Parcel in) {
this.id = in.readLong();
this.name = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(name);
}
#Override
public int describeContents() { return 0;}
public static final Parcelable.Creator<Class4> CREATOR
= new Parcelable.Creator<Class4>() {
public Class4 createFromParcel(Parcel in) {
return new Class4(in);
}
public Class4[] newArray(int size) {
return new Class4[size];
}
};
}
I used Serializable in all classes for exchange(read/write object) data via Socket channel.
I passed data from my first activity to second activity following way:
First Activity:
Class1 class1 = ...;
Intent secondActivity = new Intent(FirstActivity.this, SecondActivity.class);
orderedProductsActivity.putExtra("mydata", (Parcelable)class1);
startActivity(secondActivity);
Second Activity:
Class1 class1 = (Class1) getIntent().getParcelableExtra("mydata");

I had this issue in the past, in my case it was related with ArrayList, can you try to do:
array = (ArrayList<Long>) in.readSerializable();
and
dest.writeSerializable(array);
instead of using writeParcelableArray

Related

Pass ArrayList of Parcelable objects throws error

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];
}
};
}
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());
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.

readParcelable returns null

I try to pass a News class to an activity, so I implemented the Parcelable interface. Inside News I have two classes implementing Parcelable too, Image and Date
The matter is that my News object at the end contains null for fields image and date.
Here my code:
News.java
public class News implements Parcelable {
public static final String TAG = "model_news";
private JSONObject object;
private int id;
private String type;
private String title;
private Boolean comment_disabled;
private String category_name;
private String url;
private Image images;
private Date date;
private Boolean is_video;
public News(JSONObject object) {
this.object = object;
try {
id = Integer.parseInt(object.getString("id"));
type = object.getString("type");
title = object.getString("title");
comment_disabled = object.getBoolean("comment_disabled");
category_name = object.getString("category_name");
url = object.getString("url");
if (!object.isNull("images")) {
images = new Image(object.getJSONObject("images"));
}
date = new Date(object.getJSONObject("date"));
is_video = object.getBoolean("is_video");
} catch (JSONException e) {
Log.e(TAG, e.getMessage());
}
}
protected News(Parcel in) {
id = in.readInt();
type = in.readString();
title = in.readString();
category_name = in.readString();
url = in.readString();
images = (Image) in.readParcelable(Image.class.getClassLoader());
date = (Date) in.readParcelable(Date.class.getClassLoader());
is_video = in.readByte() != 0;
comment_disabled = in.readByte() != 0;
}
public static final Creator<News> CREATOR = new Creator<News>() {
#Override
public News createFromParcel(Parcel in) {
return new News(in);
}
#Override
public News[] newArray(int size) {
return new News[size];
}
};
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(type);
dest.writeString(title);
dest.writeByte((byte) (comment_disabled ? 1 : 0));
dest.writeString(category_name);
dest.writeString(url);
dest.writeParcelable(images, flags);
dest.writeParcelable(date, flags);
dest.writeByte((byte) (is_video ? 1 : 0));
}
#Override
public int describeContents() {
return 0;
}
}
Image.java
public class Image implements Parcelable {
public static final String TAG = "model_image";
private JSONObject imageObj;
private JSONObject original;
private String source;
private int width;
private Drawable image;
public Image(JSONObject imageObj) {
this.imageObj = imageObj;
try {
original = this.imageObj.getJSONObject("original");
source = original.getString("src");
width = original.getInt("width");
} catch (JSONException e) {
e.getMessage();
}
}
protected Image(Parcel in) {
source = in.readString();
width = in.readInt();
}
public static final Creator<Image> CREATOR = new Creator<Image>() {
#Override
public Image createFromParcel(Parcel in) {
return new Image(in);
}
#Override
public Image[] newArray(int size) {
return new Image[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(source);
dest.writeInt(width);
}
}
what I'm doing wrong ?
There is mistake in the Parcelable implementation.
First of all parcelable implementation states that: the fields passed in News(Parcel in) Constructor should be written in the same sequence in writeToParcel() method. Thats called Marshalling and Unmarshalling.
Corrections:
Drawable cannot be passed a parameter in Parcelable.
News Parcelable implementation.
Missed some of the fields its just for your understanding.
public class News implements Parcelable {
public static final String TAG = "model_news";
private JSONObject object;
private int id;
private String type;
private String title;
private Boolean comment_disabled;
private String category_name;
private String url;
private Image images;
private Date date;
private Boolean is_video;
protected News(Parcel in) {
id = in.readInt();
type = in.readString();
title = in.readString();
category_name = in.readString();
url = in.readString();
}
public static final Creator<News> CREATOR = new Creator<News>() {
#Override
public News createFromParcel(Parcel in) {
return new News(in);
}
#Override
public News[] newArray(int size) {
return new News[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(type);
dest.writeString(title);
dest.writeString(category_name);
dest.writeString(url);
}
}
public class Image implements Parcelable {
public static final String TAG = "model_image";
private JSONObject imageObj;
private JSONObject original;
private String source;
private int width;
private Drawable image;
protected Image(Parcel in) {
source = in.readString();
width = in.readInt();
}
public static final Creator<Image> CREATOR = new Creator<Image>() {
#Override
public Image createFromParcel(Parcel in) {
return new Image(in);
}
#Override
public Image[] newArray(int size) {
return new Image[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(source);
dest.writeInt(width);
}
}

Parcelable does not unmarshall nested objects

I am including the whole structure below so you can see what I have done. But it is not working. When I send a NutHouse object across activities, the NutHouse arrives but the ArrayList is empty.
public class NutHouse implements Parcelable{
Safety safety = Safety.NICE;
String name;
String address;
ArrayList<Dog> dogs;
protected NutHouse(Parcel in) {
safety = in.readParcelable(Safety.class.getClassLoader());
name = in.readString();
address = in.readString();
dogs = in.createTypedArrayList(Dog.CREATOR);
mice = in.createTypedArrayList(Mouse.CREATOR);
}
public static final Creator<NutHouse> CREATOR = new Creator<NutHouse>() {
#Override
public NutHouse createFromParcel(Parcel in) {
return new NutHouse(in);
}
#Override
public NutHouse[] newArray(int size) {
return new NutHouse[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(safety, flags);
dest.writeString(name);
dest.writeString(address);
dest.writeTypedList(dogs);
dest.writeTypedList(mice);
}
}
class Dog implements Parcelable{
String name;
String owner;
ArrayList<Show> shows;
HashMap<String,String> friends;
protected Dog(Parcel in) {
name = in.readString();
owner = in.readString();
shows = in.createTypedArrayList(Show.CREATOR);
}
public static final Creator<Dog> CREATOR = new Creator<Dog>() {
#Override
public Dog createFromParcel(Parcel in) {
return new Dog(in);
}
#Override
public Dog[] newArray(int size) {
return new Dog[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(owner);
dest.writeTypedList(shows);
}
}
class Show implements Parcelable{
String address;
int placement;
protected Show(Parcel in) {
address = in.readString();
placement = in.readInt();
}
public static final Creator<Show> CREATOR = new Creator<Show>() {
#Override
public Show createFromParcel(Parcel in) {
return new Show(in);
}
#Override
public Show[] newArray(int size) {
return new Show[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(address);
dest.writeInt(placement);
}
}
enum Safety implements Parcelable{
NICE,PET,WILD;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(final Parcel dest, final int flags) {
dest.writeInt(ordinal());
}
public static final Parcelable.Creator<Safety> CREATOR = new Parcelable.Creator<Safety>() {
#Override
public Safety createFromParcel(final Parcel source) {
return Safety.values()[source.readInt()];
}
#Override
public Safety[] newArray(final int size) {
return new Safety[size];
}
};
}

Send Parcelable object to another activity

I got 3 classes. Series, Season and Episodes.
The Series class got a list of Season objects and the Season class got a list of Episode objects.
I want to send the Series object to the other activity like this.
Intent intent = new Intent(context, OtherActivity.class);
intent.putExtra("series", (Parcelable)seriesObject);
But I get a NullPointerException.
Here are the classes that implements Parcelable.
Series class:
public class Series implements Parcelable {
private int seasonCount;
public ArrayList<Season>seasons;
private String seriesName;
private int lastSeenSeason = 0;
private int lastSeenEpisode = 0;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(seasonCount);
dest.writeTypedList(seasons);
dest.writeString(seriesName);
dest.writeInt(lastSeenSeason);
dest.writeInt(lastSeenEpisode);
}
private Series(Parcel in){
seasonCount = in.readInt();
in.readTypedList(seasons, Season.CREATOR);
seriesName = in.readString();
lastSeenSeason = in.readInt();
lastSeenEpisode = in.readInt();
}
public static final Parcelable.Creator<Series> CREATOR = new Parcelable.Creator<Series>() {
public Series createFromParcel(Parcel in) {
return new Series(in);
}
public Series[] newArray(int size) {
return new Series[size];
}
};
Season class:
public class Season implements Parcelable{
private int seasonNo;
private int episodeCount;
public ArrayList<Episode> episodes;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(seasonNo);
dest.writeInt(episodeCount);
dest.writeTypedList(episodes);
}
private Season(Parcel in){
this.seasonNo = in.readInt();
episodeCount = in.readInt();
in.readTypedList(episodes, Episode.CREATOR);
}
public static final Parcelable.Creator<Season> CREATOR = new Parcelable.Creator<Season>() {
public Season createFromParcel(Parcel in) {
return new Season(in);
}
public Season[] newArray(int size) {
return new Season[size];
}
};
and the Episode class:
public class Episode implements Parcelable{
private int episodeNo;
private boolean episodeSeen;
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(episodeNo);
dest.writeByte((byte) (episodeSeen ? 1 : 0));
}
private Episode(Parcel in){
episodeNo = in.readInt();
episodeSeen = in.readByte() != 0;
}
public static final Parcelable.Creator<Episode> CREATOR = new Parcelable.Creator<Episode>() {
public Episode createFromParcel(Parcel in) {
return new Episode(in);
}
public Episode[] newArray(int size) {
return new Episode[size];
}
};
You should initialize your arrays:
public ArrayList<Episode> episodes = new ArrayList<Episode>();
public ArrayList<Season> seasons = new ArrayList<Season>();
otherwise readTypedList will fail.

Nested parcelable object not reading

I'm trying to parcel an object which contains some string/int variables and an object variable. The strings and int's are working, but not the nested object. I understand I would have to it also parcelable, but I'm apparently doing something wrong=. In my nested class, the writeToParcel method gets called (I check with a Log.d() call), but the createFromParcel() doesn't. I end up getting a null object. This is my simplified code:
public class MyClass implements Parcelable {
public MyClass() {
}
private Integer id;
private String name;
private MyOtherClass otherClass = new MyOtherClass();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public OtherClass getOtherClass() {
return otherClass;
}
public void setOtherClass(OtherClass otherClass) {
this.otherClass = otherClass;
}
public static final Parcelable.Creator<MyClass> CREATOR
= new Parcelable.Creator<MyClass>() {
public MyClass createFromParcel(Parcel in) {
return new MyClass(in);
}
public MyClass[] newArray(int size) {
return new MyClass[size];
}
};
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(id);
dest.writeParcelable(otherClass, flags);
}
private MyClass(Parcel in) {
name = in.readString();
id = in.readInt();
otherClass = (OtherClass) in.readParcelable(OtherClass.class.getClassLoader());
}
}
class MyOtherClass implements Parcelable {
public OtherClass() {
}
private String resourcePreviewURL;
public String getResourcePreviewURL() {
return resourcePreviewURL;
}
public void setResourcePreviewURL(String resourcePreviewURL) {
this.resourcePreviewURL = resourcePreviewURL;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
Log.d("parcel", "write to parcel"); // this gets called
out.writeString(resourcePreviewURL);
}
public static final Parcelable.Creator<MyOtherClass> CREATOR
= new Parcelable.Creator<MyOtherClass>() {
public MyOtherClass createFromParcel(Parcel in) {
Log.d("parcel", "create from parcel"); // this doesn't get called
return new MyOtherClass(in);
}
public ResourcePreviews[] newArray(int size) {
return new ResourcePreviews[size];
}
};
private OtherClass(Parcel in) {
Log.d("parcel", "read from parcel"); // this doesn't get called
resourcePreviewURL = in.readString();
}
}
I solved this by changing the order in which I write/read from the Parcel. I made the dest.writeParcelable(otherClass, flags); and the otherClass = (OtherClass) in.readParcelable(OtherClass.class.getClassLoader()); calls to be the first in their methods and it started working. Is that an issue?
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(otherClass, flags);
dest.writeString(name);
dest.writeInt(id);
}
private MyClass(Parcel in) {
otherClass = (OtherClass) in.readParcelable(OtherClass.class.getClassLoader());
name = in.readString();
id = in.readInt();
}

Categories

Resources