8

I'm trying to serialize my location class (using android.location class)

but, it gives me an error!

11-21 21:25:37.337: W/System.err(3152): java.io.NotSerializableException: android.location

So, I tried to extend the android.location.Location class.

private class NewLocation extends Location implements Serializable {
        private String Provider;
        private double Latitude, Longitude, Altitude;

private float bear;
        public NewLocation(Location l) {
            super(l);
            Provider = l.getProvider();
            Latitude = l.getLatitude();
            Longitude = l.getLongitude();
            Altitude = l.getAltitude();
            bear = l.getBearing();
        }
    }

After that, i tried to serialize the extended class, but the same error.

Here is the serialization code

 public static byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutput oos = new ObjectOutputStream(bao);
        byte[] data = null;
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        data = bao.toByteArray();
        return data;
    }

why this error?

Entreco
  • 12,738
  • 8
  • 75
  • 95
user3017494
  • 83
  • 1
  • 4
  • To serialize a class you need to make sure all other classes are also Serializable that your NewLocation is referencing. – saiful103a Nov 21 '13 at 12:41

3 Answers3

12

Android's Location class already implements Parcelable. So you are better off with it rather than implementing your own Serialization.

Simply use the following to get bytes out from Location:

Parcel p = Parcel.obtain();
objLocation.writeToParcel(p, 0);
final byte[] b = p.marshall();      //now you've got bytes
p.recycle();

However, you should not save bytes (in persistent storage) from Parecelable object for later use because it is designed for high-performance IPC transport, and is not a general-purpose serialization mechanism.

waqaslam
  • 67,549
  • 16
  • 165
  • 178
  • 1
    @ArthurMelo you need to use **unmarshall** method for the reverse process. [for example](http://stackoverflow.com/a/18000094/966550) – waqaslam Dec 06 '16 at 16:02
2

You can not make a non-serializable class serializable just implementing the Serializable interface. A serializable class must inherit from a serializable class (if an inherited class) and have all its attributes serializable themselves.

All subtypes of a serializable class are themselves serializable. http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

However, if you want to serialize a Parcelable class it is still possible, but surely it would not be a good practice.

Massimo
  • 3,436
  • 4
  • 40
  • 68
2

I needed to serialize Location with most of it's members as well, not just latitude and longitude. I ended up writing my own Serializable class. The source code is bellow. The usage would be:

SerializableLocation serializable = new SerializableLocation(fromLocation);
Location toLocation = serializable.toLocation();

Few notes:

  1. Location's extras (Bundle) are not serialized
  2. Information is original Location coming from mock provider or not is lost. Location.setIsFromMockProvider can be called only by the system.

Here is the source code:

import android.location.Location;
import android.os.Build;

import androidx.annotation.NonNull;

import java.io.Serializable;

public class SerializableLocation implements Serializable {

    private static final long serialVersionUID = 1L;

    private static final int HAS_ALTITUDE_MASK                      = 1;
    private static final int HAS_SPEED_MASK                         = 2;
    private static final int HAS_BEARING_MASK                       = 4;
    private static final int HAS_HORIZONTAL_ACCURACY_MASK           = 8;
    private static final int HAS_MOCK_PROVIDER_MASK                 = 16;
    private static final int HAS_VERTICAL_ACCURACY_MASK             = 32;
    private static final int HAS_SPEED_ACCURACY_MASK                = 64;
    private static final int HAS_BEARING_ACCURACY_MASK              = 128;
    private static final int HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK  = 256;

    private String provider;
    private long   time                             = 0;
    private long   elapsedRealtimeNanos             = 0;
    private double elapsedRealtimeUncertaintyNanos  = 0.0f;
    private double latitude                         = 0.0;
    private double longitude                        = 0.0;
    private double altitude                         = 0.0f;
    private float  speed                            = 0.0f;
    private float  bearing                          = 0.0f;
    private float  horizontalAccuracyMeters         = 0.0f;
    private float  verticalAccuracyMeters           = 0.0f;
    private float  speedAccuracyMetersPerSecond     = 0.0f;
    private float  bearingAccuracyDegrees           = 0.0f;
    private int    fieldsMask                       = 0;
//  private Bundle extras = null;

    private boolean hasElapsedRealtimeUncertaintyNanos() {
        return (fieldsMask & HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK) != 0;
    }

    private boolean hasAltitude() {
        return (fieldsMask & HAS_ALTITUDE_MASK) != 0;
    }

    private boolean hasSpeed() {
        return (fieldsMask & HAS_SPEED_MASK) != 0;
    }

    private boolean hasBearing() {
        return (fieldsMask & HAS_BEARING_MASK) != 0;
    }

    private boolean hasAccuracy() {
        return (fieldsMask & HAS_HORIZONTAL_ACCURACY_MASK) != 0;
    }

    private boolean hasVerticalAccuracy() {
        return (fieldsMask & HAS_VERTICAL_ACCURACY_MASK) != 0;
    }

    private boolean hasSpeedAccuracy() {
        return (fieldsMask & HAS_SPEED_ACCURACY_MASK) != 0;
    }

    private boolean hasBearingAccuracy() {
        return (fieldsMask & HAS_BEARING_ACCURACY_MASK) != 0;
    }

    private boolean isFromMockProvider() {
        return (fieldsMask & HAS_MOCK_PROVIDER_MASK) != 0;
    }

    public SerializableLocation(@NonNull Location l) {

        provider             = l.getProvider();
        time                 = l.getTime();
        elapsedRealtimeNanos = l.getElapsedRealtimeNanos();
        latitude             = l.getLatitude();
        longitude            = l.getLongitude();

        if (l.hasAltitude()) {
            altitude = l.getAltitude();
            fieldsMask |= HAS_ALTITUDE_MASK;
        }
        if (l.hasSpeed()) {
            speed = l.getSpeed();
            fieldsMask |= HAS_SPEED_MASK;
        }
        if (l.hasBearing()) {
            bearing = l.getBearing();
            fieldsMask |= HAS_BEARING_MASK;
        }
        if (l.hasAccuracy()) {
            horizontalAccuracyMeters = l.getAccuracy();
            fieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            if (l.hasVerticalAccuracy()) {
                verticalAccuracyMeters = l.getVerticalAccuracyMeters();
                fieldsMask |= HAS_VERTICAL_ACCURACY_MASK;
            }
            if (l.hasSpeedAccuracy()) {
                speedAccuracyMetersPerSecond =
                    l.getSpeedAccuracyMetersPerSecond();
                fieldsMask |= HAS_SPEED_ACCURACY_MASK;
            }
            if (l.hasBearingAccuracy()) {
                bearingAccuracyDegrees = l.getBearingAccuracyDegrees();
                fieldsMask |= HAS_BEARING_ACCURACY_MASK;
            }
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

            if (l.hasElapsedRealtimeUncertaintyNanos()) {
                elapsedRealtimeUncertaintyNanos =
                    l.getElapsedRealtimeUncertaintyNanos();
                fieldsMask |= HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK;
            }
        }

        if (l.isFromMockProvider()) {
            fieldsMask |= HAS_MOCK_PROVIDER_MASK;
        }
    }

    public Location toLocation() {

        Location l = new Location(provider);

        l.setTime(time);
        l.setElapsedRealtimeNanos(elapsedRealtimeNanos);
        l.setLatitude(latitude);
        l.setLongitude(longitude);

        if (hasAltitude()) {
            l.setAltitude(altitude);
        }
        if (hasSpeed()) {
            l.setSpeed(speed);
        }
        if (hasBearing()) {
            l.setBearing(bearing);
        }
        if (hasAccuracy()) {
            l.setAccuracy(horizontalAccuracyMeters);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            if (hasVerticalAccuracy()) {
                l.setVerticalAccuracyMeters(verticalAccuracyMeters);
            }
            if (hasSpeedAccuracy()) {
                l.setSpeedAccuracyMetersPerSecond(speedAccuracyMetersPerSecond);
            }
            if (hasBearingAccuracy()) {
                l.setBearingAccuracyDegrees(bearingAccuracyDegrees);
            }
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

            if (hasElapsedRealtimeUncertaintyNanos()) {
                l.setElapsedRealtimeUncertaintyNanos(
                    elapsedRealtimeUncertaintyNanos
                );
            }
        }

//        l.setIsFromMockProvider(isFromMockProvider());

        return l;
    }
}
Viktor Brešan
  • 5,293
  • 5
  • 33
  • 36