0

In my activity I am passing around JSONObject's in a LinkedList to my fragment and when the fragment is open and I push the home button on the device I get the following error.

FATAL EXCEPTION: main
03-04 17:45:47.698: E/AndroidRuntime(18781): java.lang.RuntimeException:
Parcel: unable to marshal value
{"ShowRow":true,
 "isRowSelected":false,
 "GroupID":1, 
 "GroupName":"Security",
 "Header":true}

Ive tried encapsulating the LinkedList into my own parcelable object instead of using serialize but that didnt fix the issue. Im not being able to see where the error is occurring in my code but in the rest of the stack trace states:

03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeValue(Parcel.java:1137)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeList(Parcel.java:524)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeValue(Parcel.java:1097)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeMapInternal(Parcel.java:493)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Bundle.writeToParcel(Bundle.java:1612)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeBundle(Parcel.java:507)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.support.v4.app.FragmentState.writeToParcel(Fragment.java:132)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeTypedArray(Parcel.java:1004)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:357)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeParcelable(Parcel.java:1156)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeValue(Parcel.java:1075)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeMapInternal(Parcel.java:493)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Bundle.writeToParcel(Bundle.java:1612)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Parcel.writeBundle(Parcel.java:507)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:1961)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.app.ActivityThread.handleStopActivity(ActivityThread.java:2870)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.app.ActivityThread.access$900(ActivityThread.java:127)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1168)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Handler.dispatchMessage(Handler.java:99)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.os.Looper.loop(Looper.java:137)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at android.app.ActivityThread.main(ActivityThread.java:4476)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at java.lang.reflect.Method.invokeNative(Native Method)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at java.lang.reflect.Method.invoke(Method.java:511)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:816)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:583)
03-04 17:45:47.698: E/AndroidRuntime(18781):    at dalvik.system.NativeStart.main(Native Method)

So I know it has something to do with how the activity is trying to save state but how can I catch this or prevent it from happening.

Hamid Shatu
  • 9,664
  • 4
  • 30
  • 41
James andresakis
  • 5,335
  • 9
  • 53
  • 88

1 Answers1

1

Android is reporting that it doesn't know how to convert (e.g. mashall) the values that you are giving to be written to the Parcel. The exception stack trace shows that writeList() is being invoked. I expect the JSONObject that you mention above isn't following the rules for writeValue() and the exception is being thrown as a result.

The rules for writeValue() are explained here:

http://developer.android.com/reference/android/os/Parcel.html#writeValue(java.lang.Object)

Make sure that the objects that you store are one of the listed types or implement Serializable. I suspect they don't and if you don't have control over the implementation of that JSONObject type you'll probably need to iterate through the list yourself and convert whatever values are there to Strings or an array of Strings and write them out yourself using writeString() or writeStringArray() respectively.

See also How can I make my custom objects Parcelable? for a good example of implementing parcelable.

If you store something in a Serializable class, whatever you store in there also has to implement Serializable, so just placing objects inside of a Serializable container won't work.

Here's what worked for me, given your description:

public class JSONStore implements Parcelable {
    private LinkedList<JSONObject> list;

public JSONStore(int numobjects)
{
    list = new LinkedList();
    try {
                    //generate some test JSON
        for (int i = 0; i < numobjects; i++) {
            JSONObject j = new JSONObject("{ \"test\":\"" + i + "\" }");
            Log.i("JSON", j.toString());
            list.add(j);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public int describeContents() {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public void writeToParcel(Parcel out, int arg1) {
    // TODO Auto-generated method stub
    ArrayList<String> strings = new ArrayList<String>();


    for(JSONObject j : list)
    {
        strings.add(j.toString());
    }

    out.writeStringArray(strings.toArray(new String[strings.size()]));
}

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

    public JSONStore createFromParcel(Parcel n)
    {
        return new JSONStore(n);
    }

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

private JSONStore(Parcel in) {
    list = new LinkedList();
    final String[] jsonStringValues = in.createStringArray();

    try {

        for (String s : jsonStringValues) {
            list.add(new JSONObject(s));

        }
    } catch (JSONException e) {
        e.printStackTrace();
    }

}

public String toString()
{
    String ret = "";

    for(JSONObject j : list)
    {
        ret += j.toString() + "\n";
    }

    return ret;
}

}

I don't know if you really care about the LinkedList, but regardless this general approach should get you there.

Community
  • 1
  • 1
Nik
  • 76
  • 3
  • Yeah I was hoping to avoid doing something like that. I would rather figure out a way to encapsulate the JSONObject into something serializable or parcelable if possible. – James andresakis Mar 05 '14 at 03:51
  • If you store something in a Serializable container class, whatever you store in there also has to implement Serializable, so just placing JSONObject objects inside of a Serializable container won't work. That's just Java Serialization rules in play. Parcelable is kind of labor intensive like that, but see my example above and maybe that will get you to a solution you'd be satisfied with. – Nik Mar 05 '14 at 05:46