1

I try to pass a "Set" of values from a main activity to a background service running in a different process (and vice-versa, too). As I have not found any "Bundle" nor "Message.Obj" method handling "Sets", I convert the "Set" into an "ArrayList". Sending the message with this source "ArrayList" seems to occur without error, as the service gets the Message. However, when I try to retrieve the "ArrayList" from the "Message", there occurs an error.

Here is the source code of the "Parcelable" class:

public class SavedCell implements Parcelable {
public String cssId;
public boolean isFinalized;
public boolean isInduced;
public Set<Integer> potential;

public SavedCell(Cell c) {
    this.cssId = c.cssId;
    this.isFinalized = c.isFinalized;
    this.isInduced = c.isInduced;
    this.potential = new HashSet(c.potential);
}

public SavedCell(String id, boolean f, boolean i, Set<Integer> p) {
    this.cssId = id;
    this.isFinalized = f;
    this.isInduced = i;
    this.potential = new HashSet(p);
}

public SavedCell(Parcel p) {
    this.cssId = p.readString();
    this.isFinalized = (p.readByte() != 0);
    this.isInduced = (p.readByte() != 0);

    int[] potentialArray = p.createIntArray();
    this.potential = new HashSet();
    for (int i : potentialArray) {
        this.potential.add(i);
    }
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.cssId);
    dest.writeByte((byte) (this.isFinalized ? 1 : 0));
    dest.writeByte((byte) (this.isInduced ? 1 : 0));

    int[] potentialArray = new int[this.potential.size()];
    int idx = 0;
    for (Iterator it=this.potential.iterator(); it.hasNext();) {
        potentialArray[idx++] = (int) it.next();
    }
    dest.writeIntArray(potentialArray);
}

public static final Creator<SavedCell> CREATOR = new Creator<SavedCell>() {
    @Override
    public SavedCell createFromParcel(Parcel in) {
        return new SavedCell(in);
    }

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

@Override
public boolean equals(Object obj) {
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    final SavedCell other = (SavedCell) obj;

    return this.cssId.equalsIgnoreCase(other.cssId);
}

}

Here is the code handling the sending of the data in the main Activity:

    public void createInitialSnapshot(Set<SavedCell> sgc, boolean initialisePuzzle) {
    ArrayList<SavedCell> bundledPuzzle = new ArrayList<>(sgc);

    if (isSolveServiceBound) {
        try {
            Bundle b = new Bundle();
            b.putParcelableArrayList("bundledPuzzle", bundledPuzzle);
            Message msg = Message.obtain(null, MSG_SAVE_INITIAL_SNAPSHOT, (initialisePuzzle) ? 1 : 0, 0, null);
            msg.setData(b);
            msg.replyTo = messengerSolveClient;
            messengerSolveService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

And finally, the code trying to retrieve the data in the background service process:

    private void saveInitialSnapShot(Message msg) {

    Bundle b = msg.getData();
    if (b == null) {
        ...
    } else {
        ...

        ArrayList<SavedCell> bundledPuzzle = b.getParcelableArrayList("bundledPuzzle");
        Set<SavedCell> sgc = new HashSet(bundledPuzzle);
...
}

When surrounding the "ArrayList bundledPuzzle = b.getParcelableArrayList("bundledPuzzle");" statement in a try-catch block, the reported exception is "android.os.BadParcelableException: ClassNotFoundException when unmarshalling: be.ema.sc.SavedCell".

ema3272
  • 1,021
  • 2
  • 13
  • 28

1 Answers1

0

Thanks to these two links: https://stackoverflow.com/a/18126250/4579081 and https://stackoverflow.com/a/11394763/4579081, I added the b.setClassLoader(getClass().getClassLoader()); statement before the ArrayList<SavedCell> bundledPuzzle = b.getParcelableArrayList("bundledPuzzle"); statement, which solved the issue. The code to retrieve the data from the Bundle now looks like this:

    private void saveInitialSnapShot(Message msg) {

    Bundle b = msg.getData();
    if (b == null) {
        ...
    } else {
        ...

        b.setClassLoader(getClass().getClassLoader());
        ArrayList<SavedCell> bundledPuzzle = b.getParcelableArrayList("bundledPuzzle");
        Set<SavedCell> sgc = new HashSet(bundledPuzzle);
        ...
    }
}
Community
  • 1
  • 1
ema3272
  • 1,021
  • 2
  • 13
  • 28