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?
Static fields in a class cannot be serialized. If the serialversionuid is different in the read class it will throw a InvalidClassException exception. If a class implements serializable then all its sub classes will also be serializable.
For serializing the object, we call the writeObject() method of ObjectOutputStream class, and for deserialization we call the readObject() method of ObjectInputStream class. We must have to implement the Serializable interface for serializing the object.
Serializable is a markable interface or we can call as an empty interface. It doesn't have any pre-implemented methods. Serializable is going to convert an object to byte stream. So the user can pass the data between one activity to another activity.
An Android device uses two different location providers to estimate its current geographic coordinates: gps on the one hand and network on the other, the latter based either on the calculated distance to multiple cell towers or on the known location of the Wi-Fi network provider to which we are connected.
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.
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.
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:
Location
's extras (Bundle
) are not serializedLocation
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With