11

I'm using Google's LatLng class from the v2 Google Play Services. That particular class is final and doesn't implement java.io.Serializable. Is there any way I can make that LatLng class implement Serializable?

public class MyDummyClass implements java.io.Serializable {
    private com.google.android.gms.maps.model.LatLng mLocation;

    // ...
}

I don't want to declare mLocation transient.

Grooveek
  • 10,046
  • 1
  • 27
  • 37
Jens Kohl
  • 5,899
  • 11
  • 48
  • 77
  • This is currently a hell of a problem for me and I don't want to make my variable transient. I had to just pass in two doubles (lat and lng) and then make them into a location or latlng where I wanted to use them. – Taslim Oseni Jul 04 '19 at 08:36

2 Answers2

30

It's not Serializable but it is Parcelable, if that would be an option instead. If not you could handle the serialization yourself:

public class MyDummyClass implements java.io.Serialiazable {
    // mark it transient so defaultReadObject()/defaultWriteObject() ignore it
    private transient com.google.android.gms.maps.model.LatLng mLocation;

    // ...

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeDouble(mLocation.latitude);
        out.writeDouble(mLocation.longitude);
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        mLocation = new LatLng(in.readDouble(), in.readDouble());
    }
}
Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
2

You can have a look at ObjectOutputStream .

First, you'll have to create a drop-in replacement for your object :

    public class SerializableLatLng implements Serializable {

    //use whatever you need from LatLng

    public SerializableLatLng(LatLng latLng) {
        //construct your object from base class
    }   

    //this is where the translation happens
    private Object readResolve() throws ObjectStreamException {
        return new LatLng(...);
    }

}

Then create an appropriate ObjectOutputSTream

public class SerializableLatLngOutputStream extends ObjectOutputStream {

    public SerializableLatLngOutputStream(OutputStream out) throws IOException {
        super(out);
        enableReplaceObject(true);
    }

    protected SerializableLatLngOutputStream() throws IOException, SecurityException {
        super();
        enableReplaceObject(true);
    }

    @Override
    protected Object replaceObject(Object obj) throws IOException {
        if (obj instanceof LatLng) {
            return new SerializableLatLng((LatLng) obj);
        } else return super.replaceObject(obj);
    }

}

Then you'll have to use these streams when serializing

private static byte[] serialize(Object o) throws Exception {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new SerializableLatLngOutputStream(baos); 
    oos.writeObject(o);
    oos.flush();
    oos.close();
    return baos.toByteArray();
}
Grooveek
  • 10,046
  • 1
  • 27
  • 37