Search code examples
androidmarshallingunmarshallingparcelableparcel

How to marshall and unmarshall a Parcelable to a byte array with help of Parcel?


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?


Solution

  • 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);