2

I'm trying to write a list of a parcelable object to a parcelable object, but I'm getting a java runtime error saying "Class not found when unmarshelling...".

Logcat

11-13 08:41:06.412: E/Parcel(791): Class not found when unmarshalling: com.firstandroidapp.EventMeta
11-13 08:41:06.412: E/Parcel(791): java.lang.ClassNotFoundException: com.firstandroidapp.EventMeta
11-13 08:41:06.412: E/Parcel(791):  at java.lang.Class.classForName(Native Method)
11-13 08:41:06.412: E/Parcel(791):  at java.lang.Class.forName(Class.java:204)
11-13 08:41:06.412: E/Parcel(791):  at java.lang.Class.forName(Class.java:169)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Parcel.readParcelableCreator(Parcel.java:2091)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Parcel.readParcelable(Parcel.java:2055)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Parcel.readValue(Parcel.java:1971)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Parcel.readListInternal(Parcel.java:2264)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Parcel.readList(Parcel.java:1537)
11-13 08:41:06.412: E/Parcel(791):  at com.firstandroidapp.EventHolder.<init>(EventHolder.java:36)
11-13 08:41:06.412: E/Parcel(791):  at com.firstandroidapp.EventHolder$1.createFromParcel(EventHolder.java:17)
11-13 08:41:06.412: E/Parcel(791):  at com.firstandroidapp.EventHolder$1.createFromParcel(EventHolder.java:1)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Parcel.readParcelable(Parcel.java:2062)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Parcel.readValue(Parcel.java:1971)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Parcel.readMapInternal(Parcel.java:2255)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Bundle.unparcel(Bundle.java:223)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Bundle.getParcelable(Bundle.java:1170)
11-13 08:41:06.412: E/Parcel(791):  at android.content.Intent.getParcelableExtra(Intent.java:4501)
11-13 08:41:06.412: E/Parcel(791):  at com.firstandroidapp.AddSubjectFragment.onActivityResult(AddSubjectFragment.java:198)
11-13 08:41:06.412: E/Parcel(791):  at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:166)
11-13 08:41:06.412: E/Parcel(791):  at android.app.Activity.dispatchActivityResult(Activity.java:5322)
11-13 08:41:06.412: E/Parcel(791):  at android.app.ActivityThread.deliverResults(ActivityThread.java:3363)
11-13 08:41:06.412: E/Parcel(791):  at android.app.ActivityThread.handleSendResult(ActivityThread.java:3410)
11-13 08:41:06.412: E/Parcel(791):  at android.app.ActivityThread.access$1100(ActivityThread.java:141)
11-13 08:41:06.412: E/Parcel(791):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1304)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Handler.dispatchMessage(Handler.java:99)
11-13 08:41:06.412: E/Parcel(791):  at android.os.Looper.loop(Looper.java:137)
11-13 08:41:06.412: E/Parcel(791):  at android.app.ActivityThread.main(ActivityThread.java:5103)
11-13 08:41:06.412: E/Parcel(791):  at java.lang.reflect.Method.invokeNative(Native Method)
11-13 08:41:06.412: E/Parcel(791):  at java.lang.reflect.Method.invoke(Method.java:525)
11-13 08:41:06.412: E/Parcel(791):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
11-13 08:41:06.412: E/Parcel(791):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
11-13 08:41:06.412: E/Parcel(791):  at dalvik.system.NativeStart.main(Native Method)
11-13 08:41:06.412: E/Parcel(791): Caused by: java.lang.NoClassDefFoundError: com/firstandroidapp/EventMeta
11-13 08:41:06.412: E/Parcel(791):  ... 32 more
11-13 08:41:06.412: E/Parcel(791): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.firstandroidapp.EventMeta" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib]]
11-13 08:41:06.412: E/Parcel(791):  at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:53)
11-13 08:41:06.412: E/Parcel(791):  at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
11-13 08:41:06.412: E/Parcel(791):  at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
11-13 08:41:06.412: E/Parcel(791):  ... 32 more

As far as I understand the error occurs while writing the list of EventMeta to EventHolder.

Here are the implementations of both EventHolder and EventMeta.

EventHolder

public class EventHolder implements Parcelable {

    public List<EventMeta> mEMList = new ArrayList<EventMeta>();
    public Event mEvent;

    @SuppressWarnings("rawtypes")
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public EventHolder createFromParcel(Parcel in) {
            return new EventHolder(in); 
        }

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


    public EventHolder(List<EventMeta> mEMList, Event mEvent) {
        this.mEMList = mEMList;
        this.mEvent = mEvent;
    }

    public EventHolder(Parcel in){
        mEMList= new ArrayList<EventMeta>();
        in.readTypedList(mEMList, EventMeta.CREATOR);
        this.mEvent = in.readParcelable(null);
    }

    public int describeContents(){
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        dest.writeTypedList(mEMList); 
        dest.writeParcelable(mEvent, flags);
    }
}

EventMeta

public class EventMeta implements Parcelable {

    long mEventMetaId;
    long mEventId;
    Date mStartDate;

    @SuppressWarnings("rawtypes")
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public EventMeta createFromParcel(Parcel in) {
            return new EventMeta(in);
        }

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

    public EventMeta(long mEventMetaId, long mEventId, Date mStartDate) {
        this.mEventMetaId = mEventMetaId;
        this.mEventId = mEventId;
        this.mStartDate = mStartDate;
    }

    public EventMeta(Parcel in) {
        this.mEventMetaId = in.readLong();
        this.mEventId = in.readLong();
        this.mStartDate = new Date(in.readLong());
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(this.mEventMetaId);
        dest.writeLong(this.mEventId);
        dest.writeLong(this.mStartDate.getTime());
    }

}

Is there anything wrong with my code? I double checked anything before posting but couldn't find anything out of place.

Update ##

I've used daneejela's answer and now the problem has moved to the class called 'Class` - which means the problem is partially solved.

Class extends `Event, and it looks like this:

public class Class extends Event {  

    long mClassId;
    String mClassLocation;
    long mSubjectId;

    @SuppressWarnings("rawtypes")
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public Class createFromParcel(Parcel in) {
            return new Class(in);
        }

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

    public Class(long mClassId, String location, long mSubjectId, long mEventId, int mEventPriority, String mEventTitle, String mEventNotes, long start, long end) {
        super(mEventId, mEventPriority, mEventTitle, mEventNotes, start, end);
        this.mClassId = mClassId;
        this.mClassLocation = location;
        this.mSubjectId = mSubjectId;
    }

    public Class(Parcel in){
        super(in);
        this.mClassId = in.readLong();
        this.mClassLocation = in.readString();
        this.mSubjectId = in.readLong();
    }

    public int describeContents(){
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        dest.writeLong(this.mClassId);
        dest.writeString(this.mClassLocation);
        dest.writeLong(this.mSubjectId);
    }
}

Update 2

Event

public class Event implements Parcelable {

    long mEventId;
    int mEventPriority;
    String mEventTitle;
    String mEventNotes;
    long mEventStartTime;
    long mEventEndTime;

    @SuppressWarnings("rawtypes")
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public Event createFromParcel(Parcel in) {
            return new Event(in); 
        }

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

    public Event(long id, int priority, String title, String notes, long start, long end) {
        this.mEventId = id;
        this.mEventPriority = priority;
        this.mEventTitle = title;
        this.mEventNotes = notes;
        this.mEventStartTime = start;
        this.mEventEndTime = end;
    }

    public Event(Parcel in){
        this.mEventId = in.readLong();
        this.mEventPriority = in.readInt();
        this.mEventTitle = in.readString();
        this.mEventNotes = in.readString();
        this.mEventStartTime = in.readLong();
        this.mEventEndTime = in.readLong();
    }

    public int describeContents(){
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(this.mEventId);
        dest.writeInt(this.mEventPriority);
        dest.writeString(this.mEventTitle);
        dest.writeString(this.mEventNotes);
        dest.writeLong(this.mEventStartTime);
        dest.writeLong(this.mEventEndTime);
    }
}
Asaf
  • 2,005
  • 7
  • 37
  • 59
  • 1
    Is there any particular reason you have to use the `EventMeta`? `ArrayList` is already parcelable. – Andrew Schuster Nov 13 '13 at 14:06
  • What do you mean? `EventMeta` contains information so I do need to use it. – Asaf Nov 13 '13 at 14:29
  • 1
    My apologies, I meant `EventHolder`. `EventMeta` looks fine, but in your `EventHolder`, it just feels kind of redundant to write a whole class just to associate one `Event` to a list of `EventMeta`s. – Andrew Schuster Nov 13 '13 at 14:35
  • 1
    Hm..Can you post Event code? (P.S. Does anything change if you change "public static final Parcelable.Creator CREATOR = new Parcelable.Creator()" into "public static final Parcelable.Creator CREATOR = new Parcelable.Creator()" ? ) – daneejela Nov 13 '13 at 15:25
  • @AndrewSchuster - Thank you. I think using `ArrayList` would make it much easier. Don't know why I haven't thought of it before. With that being said, I would like to leave `EventHolder` as is, since my app is far from being done, I might have to add more fields to `EventHolder` in the future. I will note to myself to come back to it when the time comes, though. Much thanks for the great idea! (P.S: Do you happen to know whether there is a performance difference between the two approaches?) – Asaf Nov 13 '13 at 20:32
  • @daneejela - That didn't work :(. I added the code for the `Event` class. Thank you! :) – Asaf Nov 13 '13 at 20:33
  • 1
    @xTCx Performance probably won't be an issue, but if you plan on passing this stuff between Activities, be aware of the memory limitations! You can't actually put that much information through the Bundle. The limit is [around 500kB](http://stackoverflow.com/questions/8552514/is-there-some-limits-in-android-bundle) – Andrew Schuster Nov 13 '13 at 20:40
  • @AndrewSchuster - I'm actually going to pass it back as an intent. Is that the same thing? Luckily `EventHolder` is limited to about 7-8 `EventMetas`. Should be enough shouldn't it? I will be cautious and test before releasing the app. Thank you! – Asaf Nov 13 '13 at 20:51
  • 1
    @xTCx Sorry, yeah, that's what I meant. You should **hopefully** be fine as long as you don't include any pictures. – Andrew Schuster Nov 13 '13 at 20:54

2 Answers2

4

Try this code

public class EventHolder implements Parcelable {
    public List mEMList = new ArrayList();
    public Event mEvent;

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public EventHolder createFromParcel(Parcel in) {
            return new EventHolder(in);
        }

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

    public EventHolder(List mEMList, Event mEvent) {
        this.mEMList = mEMList;
        this.mEvent = mEvent;
    }

    public EventHolder(Parcel in) {
        in.readList(mEMList, mEMList.getClass().getClassLoader());
        this.mEvent = in.readParcelable(mEvent.getClass().getClassLoader());
    }

    public int describeContents() {
        return 0XFE;
    }

    public void writeToParcel(Parcel dest, int flags) {
        dest.writeList(mEMList);
        dest.writeParcelable(mEvent, describeContents());
    }
}

and i have a doubt is that Event is parcelable? If not make it as parcelable.

Andrew Schuster
  • 3,229
  • 2
  • 21
  • 32
android_dev
  • 1,477
  • 12
  • 18
  • Thank you. `Event` is indeed parcelable. I've tried your solution but it doesn't work. Same error. – Asaf Nov 13 '13 at 14:30
3

Have you try with this (inside EventHolder) :

public class EventHolder implements Parcelable {

//...

public EventHolder(Parcel in){
    mEMList= new ArrayList<EventMeta>();
    in.readTypedList(mEMList, EventMeta.CREATOR);
    this.mEvent = in.readParcelable(null);
}

public int describeContents(){
    return 0;
}

public void writeToParcel(Parcel dest, int flags) {
    dest.writeTypedList(mEMList); 
    dest.writeParcelable(mEvent, flags);
}

}
daneejela
  • 13,081
  • 7
  • 38
  • 50
  • Thank you! Apparently that solved it, partially. The thing is now I get the same error, but for the class called `Class`, which extends `Event`. I'm updating my main post with the code for class. Could you please look at it? :D – Asaf Nov 13 '13 at 14:36