48

I want to marshall and unmarshall a Class that implements Parcelable to/from a byte array. I am well aware of the fact that the Parcelable representation is not stable and therefore not meant for long term storage of instances. But I have a use case where I need to serialize a object and it's not a showstopper if the unmarshalling fails because of an internal Android change. Also the class is already implementing the Parcelable interface.

Given an class MyClass implements Parcelable, how can I (ab)use the Parcelable interface for marshalling/unmarshalling?

Flow
  • 23,572
  • 15
  • 99
  • 156

2 Answers2

135

First create a helper class ParcelableUtil.java:

public class ParcelableUtil {    
    public static byte[] marshall(Parcelable parceable) {
        Parcel parcel = Parcel.obtain();
        parceable.writeToParcel(parcel, 0);
        byte[] bytes = parcel.marshall();
        parcel.recycle();
        return bytes;
    }

    public static Parcel unmarshall(byte[] bytes) {
        Parcel parcel = Parcel.obtain();
        parcel.unmarshall(bytes, 0, bytes.length);
        parcel.setDataPosition(0); // This is extremely important!
        return parcel;
    }

    public static <T> T unmarshall(byte[] bytes, Parcelable.Creator<T> creator) {
        Parcel parcel = unmarshall(bytes);
        T result = creator.createFromParcel(parcel);
        parcel.recycle();
        return result;
    }
}

With the help of the util class above, you can marshall/unmarshall instances of your class MyClass implements Parcelable like so:

Unmarshalling (with CREATOR)

byte[] bytes = …
MyClass myclass = ParcelableUtil.unmarshall(bytes, MyClass.CREATOR);

Unmarshalling (without CREATOR)

byte[] bytes = …
Parcel parcel = ParcelableUtil.unmarshall(bytes);
MyClass myclass = new MyClass(parcel); // Or MyClass.CREATOR.createFromParcel(parcel).

Marshalling

MyClass myclass = …
byte[] bytes = ParcelableUtil.marshall(myclass);
Flow
  • 23,572
  • 15
  • 99
  • 156
  • 8
    `parcel.setDataPosition(0); // this is extremely important!` this help me much. the missing of Android document of this, is really suck. – Jiang YD Dec 17 '15 at 08:26
  • 1
    Thank you very much for this tip. Implementing Parcelable (which is hugely error-prone and you will get meaningless runtime exceptions and angry customers if not done right) is such a PITA - I'm avoiding Parcelables in my code altogether and I'm using Serializables. On modern phones, the speed hit is hardly noticeable. – Martin Vysny Mar 15 '16 at 09:09
  • 2
    The only problem with this approach, however, is that unmarshalling a subclass of class that implements Parcelable will not be as straightforward. You'll need to pass along extra info from which you can judge the correct Creator to use. – bosphere Aug 13 '16 at 10:58
  • Flow, How use your util class for ParcelableArrayList case ? Thank you very much! – anthony Aug 13 '16 at 14:07
  • @Flow where to do Marshalling and UnMarshalling in Parcelable implementing class – rupesh Sep 25 '17 at 12:22
  • Working fine with custom objects. But, Is there a way to send list of data which is a custom object that extended `Parcelable`. If it's possible what modification should I make? – Chathuranga Shan Jayarathna Nov 25 '18 at 14:04
-3
public static byte[] pack(Parcelable parcelable) {
    Parcel parcel = Parcel.obtain();
    parcelable.writeToParcel(parcel, 0);
    byte[] bytes = parcel.marshall();
    parcel.recycle();
    return bytes;
}

public static <T> T unpack(byte[] bytes, Parcelable.Creator<T> creator) {
    Parcel parcel = Parcel.obtain();
    parcel.unmarshall(bytes, 0, bytes.length);
    parcel.setDataPosition(0);
    return creator.createFromParcel(parcel);
}

MyObject myObject = unpack(new byte[]{/* bytes */}, MyObject.CREATOR);
  • 2
    Please give a brief explanation of the code you posted so that it will be easier for OP to understand. – Jatin Mar 16 '14 at 23:41