如何为android.location类序列化?

时间:2013-11-21 12:35:18

标签: java android serialization location deserialization

我正在尝试序列化我的位置类(使用android.location类)

但是,它给了我一个错误!

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

所以,我试图扩展android.location.Location类。

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();
        }
    }

之后,我尝试序列化扩展类,但同样的错误。

这是序列化代码

 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;
    }

为什么会出现这个错误?

3 个答案:

答案 0 :(得分:11)

Android的Location课程已经实施 Parcelable。因此,您最好使用它而不是实现自己的序列化。

只需使用以下内容即可从bytes获取Location

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

但是,您不应该从Parecelable对象保存字节(在持久存储中)以供以后使用,因为它是专为高性能IPC传输而设计的,并不是通用的序列化机制。 / em>的

答案 1 :(得分:2)

只有实现Serializable接口,才能使不可序列化的类可序列化。 可序列化的类必须从可序列化的类继承(如果是继承的类),并且其所有属性都可以自行序列化。

可序列化类的所有子类型本身都是可序列化的。 http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

但是,如果你想序列化一个Parcelable类仍然可以,但肯定不是一个好习惯。

答案 2 :(得分:0)

我还需要将Location与其大多数成员一起序列化,而不仅仅是纬度和经度。我最终写了自己的Serializable类。源代码如下。用法是:

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

一些注意事项:

  1. Location的附加(Bundle)未序列化
  2. 信息是否是原始的Location来自模拟提供商,还是丢失了。 Location.setIsFromMockProvider只能由系统调用。

这是源代码:

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;
    }
}