解组未知类型代码,List<Byte> & List<String>

Unmarshalling unknown type code, List<Byte> & List<String>

我有一个问题 unpacking/reading Parcelable 有两个麻烦的属性,一个是 List 类型的列表,一个是包含字节数组的列表,还有一个是包含字符串的列表,错误是 正在解组未知类型代码。

The Parcelable class is a subclass of parent class Message, see below:

package x.y.z.InboxManager;

import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;

import java.util.Objects;

import x.y.z.Application.XXXApp;

public class Message implements Parcelable{

    private static String TAG = "Message";
    //client_id (same as wam_id) - String/text – Id of the JAMS unit
    private String wam_id= null;
    //severity level (Optional) currently not used
    private String level = null;
    //message  - String/text – if topic = “EMERGENCY” then value {Alias possibly having life threating emergency!} else nothing or user provided
    private String message = null;
    private String image_id = null;
    //topic - String/text – “EMERGENCY” OR "ALERT"
    private String topic = null;
    // time_of_arrival_in_milli_secs_from_epoch -Long/numerical- time of message arrival in milliseconds  from epoch based receivers device time
    private long timeofArrivalInNanoSecsFromEpoch = 0L;
    //viewed - int/numerical - 0 or 1
    private int viewed = 0;
    //image_data - byte/blob - binary data of the image (all images are assumed to be PNG)
    private byte [] imageData = null;
    //client alias  - String/text –  Alias or  friendly name associated with clientId
    private String clientAlias;
    //sql table related attributes
    public static String TABLE_NAME="ALERT_MESSAGE";
    //COLUMN_NAME_TIME_OF_ARRIVAL will be the primary  key
    public static String COLUMN_NAME_TIME_OF_ARRIVAL="TIME_OF_ARRIVAL";
    public static String COLUMN_NAME_WAM_ID="WAM_ID";
    public static String COLUMN_NAME_LEVEL="LEVEL";
    public static String COLUMN_NAME_MESSAGE="MESSAGE";
    public static String COLUMN_NAME_IMAGE_ID="IMAGE_ID";
    public static String COLUMN_NAME_TOPIC="TOPIC";
    public static String COLUMN_NAME_VIEWED="VIEWED";
    public static String COLUMN__NAME_IMAGE_DATA="IMAGE_DATA";
    //SQL
    public static final String SQL_CREATE_ENTRIES =
            "create table " + Message.TABLE_NAME + " ( "+ Message.COLUMN_NAME_TIME_OF_ARRIVAL + " INTEGER PRIMARY KEY," +
                    Message.COLUMN_NAME_WAM_ID + " TEXT," +
                    Message.COLUMN_NAME_LEVEL + " TEXT," +
                    Message.COLUMN_NAME_MESSAGE + " TEXT," +
                    Message.COLUMN_NAME_IMAGE_ID + " TEXT,"  +
                    Message.COLUMN_NAME_TOPIC + " TEXT,"+
                    Message.COLUMN_NAME_VIEWED + " BOOLEAN NOT NULL CHECK ( "+ Message.COLUMN_NAME_VIEWED+" IN (0,1))," +
                    Message.COLUMN__NAME_IMAGE_DATA + " BLOB)";

    public static final String SQL_DROP_TABLE_ENTRIES = "DROP TABLE IF EXISTS "+ Message.TABLE_NAME;
    private GetImagDataFromUrlTask getImageTask = null;

   public  void downloadImage()
    {
        getImageTask = new GetImagDataFromUrlTask(XXXApp.getContext());
        getImageTask.execute(this);
    }


    public void cancelImageDownload()
    {
        if (getImageTask!=null) {
            getImageTask.cancel(true);
        }
    }


    public Message() {

    }

    public Message(String wam_id, String level, String message, String image_id, long timeofArrivalInNanoSecsFromEpoch) {
        this.wam_id = wam_id;
        this.level = level;
        this.message = message;
        this.image_id = image_id;
        this. timeofArrivalInNanoSecsFromEpoch =  timeofArrivalInNanoSecsFromEpoch;
    }

    public  Message(Parcel in)
    {
        this.wam_id = in.readString();
        this.level = in.readString();
        this.message = in.readString();
        this.image_id = in.readString();
        this.timeofArrivalInNanoSecsFromEpoch = in.readLong();
        if (this.imageData!=null) {
            in.readByteArray(this.imageData);
        }
    }

    public String getWam_id() {
        return wam_id;
    }

    public void setWam_id(String wam_id) {
        this.wam_id = wam_id;
    }

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getImage_id() {
        return image_id;
    }

    public void setImage_id(String image_id) {
        this.image_id = image_id;
    }

    public long getTimeofArrivalInMilliSecsFromEpoch() {
        return timeofArrivalInNanoSecsFromEpoch;
    }

    public void setTimeofArrivalInMilliSecsFromEpoch(long timeofArrivalInNanoSecsFromEpoch) {
        this.timeofArrivalInNanoSecsFromEpoch = timeofArrivalInNanoSecsFromEpoch;
    }

    public String getTopic() {
        return topic;
    }

    public void setTopic(String topic) {
        this.topic = topic;
    }

    public int getViewed() {
        return viewed;
    }

    public void setViewed(int viewed) {
        this.viewed = viewed;
    }

    public byte[] getImageData() {
        return imageData;
    }

    public void setImageData(byte[] imageData) {
        this.imageData = imageData;
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.wam_id);
        dest.writeString(this.level);
        dest.writeString(this.message);
        dest.writeString(this.image_id);
        dest.writeLong(this.timeofArrivalInNanoSecsFromEpoch);
        dest.writeByteArray(imageData);
    }

    public static final Parcelable.Creator<Message> CREATOR= new Parcelable.Creator<Message>() {

        @Override
        public Message createFromParcel(Parcel source) {
// TODO Auto-generated method stub
            return new Message(source);  //using parcelable constructor
        }

        @Override
        public Message[] newArray(int size) {
            return new Message[size];
        }
    };



    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Message that = (Message) o;

        return timeofArrivalInNanoSecsFromEpoch == that.timeofArrivalInNanoSecsFromEpoch;
           //TODO: update equivalency
        /*if (message!=null) {
            return timeofArrivalInNanoSecsFromEpoch == that.timeofArrivalInNanoSecsFromEpoch && message.equalsIgnoreCase(that.message);
        }
        else
        {
            return timeofArrivalInNanoSecsFromEpoch == that.timeofArrivalInNanoSecsFromEpoch && wam_id.equalsIgnoreCase(that.wam_id);
        }*/
    }

    @Override
    public String toString() {
        return "Message{" +
                "wam_id='" + wam_id + '\'' +
                ", level='" + level + '\'' +
                ", message='" + message + '\'' +
                ", image_id='" + image_id + '\'' +
                ", topic='" + topic + '\'' +
                ", timeofArrivalInMillisecs=" + timeofArrivalInNanoSecsFromEpoch +
                ", viewed=" + viewed +
                '}';
    }

    @Override
    public int hashCode() {

        return Objects.hash(timeofArrivalInNanoSecsFromEpoch);
    }


}

子出现错误class 紧急,见下,参考属性:

in.readList(extras,Byte[].class.getClassLoader());
in.readList(extrasFormat,Formats.ExtrasFormat.class.getClassLoader());

整个class:

package x.y.z.InboxManager;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;

public class Emergency extends  Message implements Parcelable {


    private String clientAlias;
    private String topic;
    private Long timeOfPublish;
    private Double lat;
    private Double lon;
    private List<Byte[]> extras = new ArrayList<Byte[]>();
    private List<Formats.ExtrasFormat> extrasFormat = new  ArrayList<Formats.ExtrasFormat>();


    public  Emergency()
    {

    }


    public  Emergency(Parcel in)
    {
        //super(in.readString(),in.readString(),in.readString(),in.readString(),in.readLong());
        super(in);
        this.clientAlias = in.readString();
        this.topic = in.readString();
        this.timeOfPublish = in.readLong();
        this.lat = in.readDouble();
        this.lon = in.readDouble();
        super.setViewed(in.readInt());

        in.readList(extras,Byte[].class.getClassLoader());
        in.readList(extrasFormat,Formats.ExtrasFormat.class.getClassLoader());

    }


    public Emergency(String clientId,String level,String message,String imageId,Long timeOfArrival,String clientAlias, String topic,Long timeOfPublish,Double lat, Double lon,int viewed,List<Byte[]> extras,List<Formats.ExtrasFormat> extrasFormats)
    {
      super(clientId,level,message,imageId,timeOfArrival);
      super.setViewed(viewed);
      this.clientAlias = clientAlias;
      this.topic = topic;
      this.timeOfPublish = timeOfPublish;
      this.lat = lat;
      this.lon = lon;
      this.extras = extras;
      this.extrasFormat = extrasFormats;

    }

  public String getClientAlias() {
    return clientAlias;
  }

  @Override
  public String getTopic() {
    return topic;
  }

  public Long getTimeOfPublish() {
    return timeOfPublish;
  }

  public Double getLat() {
    return lat;
  }

  public Double getLon() {
    return lon;
  }

  public List<Byte[]> getExtras() {
    return extras;
  }

  public List<Formats.ExtrasFormat> getExtrasFormat() {
    return extrasFormat;
  }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {

        super.writeToParcel(dest,flags);
        dest.writeString(this.clientAlias);
        dest.writeString(this.topic);
        dest.writeLong( this.timeOfPublish);
        dest.writeDouble(this.lat);
        dest.writeDouble(this.lon);
        dest.writeInt(this.getViewed());

        dest.writeList(extras);
        dest.writeList(extrasFormat);
    }

    public static final Parcelable.Creator<Emergency> CREATOR= new Parcelable.Creator<Emergency>() {

        @Override
        public Emergency createFromParcel(Parcel source) {
// TODO Auto-generated method stub
            return new Emergency(source);  //using parcelable constructor
        }

        @Override
        public Emergency[] newArray(int size) {
            return new Emergency[size];
        }
    };


}

Exception/Error 日志如下:

Process: x.y.z, PID: 14292
java.lang.RuntimeException: Unable to start service x.y.z.services.MqttBrokerService@3a0f1bd with Intent { act=x.y.z.action.EMERGENCY_MESSAGE cmp=x.y.z/.services.MqttBrokerService (has extras) }: java.lang.RuntimeException: Parcel android.os.Parcel@748514: Unmarshalling unknown type code 6357111 at offset 408
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3347)
    at android.app.ActivityThread.-wrap21(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1586)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6145)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
 Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@748514: Unmarshalling unknown type code 6357111 at offset 408
    at android.os.Parcel.readValue(Parcel.java:2444)
    at android.os.Parcel.readListInternal(Parcel.java:2793)
    at android.os.Parcel.readList(Parcel.java:1836)
    at x.y.z.InboxManager.Emergency.<init>(Emergency.java:65)
    at x.y.z.InboxManager.Emergency.createFromParcel(Emergency.java:139)
    at x.y.z.InboxManager.Emergency.createFromParcel(Emergency.java:134)

如何正确地将这些编组和解编为列表?

谢谢

在超级class中,这看起来是错误的:

public  Message(Parcel in)
{
    ...
    if (this.imageData!=null) {
        in.readByteArray(this.imageData);
    }
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    ...
    dest.writeByteArray(imageData);
}

我相对确定 this.imageData 到那时将永远是 null,这意味着您不会有匹配的 "read" 来搭配 "write"在 writeToParcel()。相反,您应该使用 createByteArray():

public  Message(Parcel in)
{
    ...
    this.imageData = in.createByteArray();
}

那我们就要考虑subclass:

public  Emergency(Parcel in)
{
    ...
    in.readList(extrasFormat,Formats.ExtrasFormat.class.getClassLoader());
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    ...
    dest.writeList(extrasFormat);
}

Formats.ExtrasFormat 实现的是 Parcelable 还是 Serializable?如果没有,我认为这不会奏效。如果是这样,那么可能只需修复 superclass 即可。