如何为android.location类进行序列化?

8
我试图序列化我的位置类(使用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;
    }

为什么会出现这个错误?

要对一个类进行序列化,你需要确保所有被 NewLocation 引用的其他类也都是可序列化的。 - saiful103a
3个回答

12

Android的Location类已经实现了Parcelable。因此,与其自己实现序列化,不如使用它。

只需使用以下代码从Location中获取bytes

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

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


1
@ArthurMelo 你需要使用 unmarshall 方法来进行反向处理。例如 - waqaslam

3

我需要将 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;
    }
}

2
通过实现Serializable接口,你无法使一个非可序列化的类变得可序列化。 一个可序列化的类必须继承自一个可序列化的类(如果是继承类),并且其所有属性本身都必须是可序列化的。 一个可序列化类的所有子类型也都是可序列化的。 http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html 然而,如果要序列化一个Parcelable类,则仍然可以这样做,但这肯定不是一个好的做法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接