Mark Murphy
Mark Murphy

Reputation: 1660

Intent extras seem to get corrupted

Boy, this is a weird one.

I'm sending an intent to a service.

public void updatePortfolio(VehiclePortfolio vehiclePortfolio) {
    GenericParcel gp = new GenericParcel(vehiclePortfolio);
    Intent apiIntent = new Intent(context, ApiRequestService.class);
    apiIntent.putExtra(Constants.ARG_REQUEST, Constants.REQUEST_UPDATE_PORTFOLIO);
    apiIntent.putExtra(Constants.ARG_VEHICLE_PORTFOLIO, gp);
    // Try getting object back here
    //gp = apiIntent.getParcelableExtra(Constants.ARG_VEHICLE_PORTFOLIO);
    VehiclePortfolio vp = (VehiclePortfolio)gp.getObject();
    String s = apiIntent.getStringExtra(Constants.ARG_REQUEST);
    vehiclePortfolio = (VehiclePortfolio) gp.getObject();

    // .putExtra(Constants.ARG_VEHICLE_PORTFOLIO, b);
    context.startService(apiIntent);
}

When I check the extras in the intent at the end of this function they look fine as shown below.

 mMap   HashMap  (id=830037731672)  
[0] HashMap$HashMapEntry  (id=830037731800) 
    key "ARG_VEHICLE_PORTFOLIO" (id=830038543392)   
    value   GenericParcel  (id=830038204888)    
        o   VehiclePortfolio  (id=830038244704) 
            configuration   VehicleConfiguration  (id=830038258216) 
            id  "1375379159508" (id=830038245672)   
            optionals   VehiclePortfolio$_Fields[5]  (id=830038244744)  
            priceReport VehiclePriceReport  (id=830038312960)   
            quotes  ArrayList  (id=830038417704)    
            timestamp   "2013-08-01T17:46:31.000Z" (id=830038536424)    
[1] HashMap$HashMapEntry  (id=830037731768) 
    key "ARG_REQUEST" (id=830037687416) 
    value   Integer  (id=830019251512)  
        value   6   

Then, when the service receives the intent, this is what the extras look like. Notice that the vehiclePortfolio has been overwritten on top of ARG_REQUEST extra and the key and value have been swapped. (What?!?)

  mMap  HashMap  (id=830038833832)  
[0] HashMap$HashMapEntry  (id=830039001656) 
    key VehiclePortfolio  (id=830038934408) 
        configuration   VehicleConfiguration  (id=830038936272) 
        id  "1375379159508" (id=830038936128)   
        optionals   null    
        priceReport VehiclePriceReport  (id=830038941176)   
        quotes  ArrayList  (id=830038963264)    
        timestamp   "2013-08-01T17:46:31.000Z" (id=830039001424)    
    value   "ARG_REQUEST" (id=830039001576) 
[1] HashMap$HashMapEntry  (id=830038834568) 
    key "ARG_VEHICLE_PORTFOLIO" (id=830038833888)   
    value   GenericParcel  (id=830038834512)    
        o   Parcel  (id=830037350528)   
            mNativePtr  1891558544  
            mOwnsNativeParcelObject true    
            mStack  null    

Below is the code for GenericParcel which I suspect to be the culprit. If I do a test and pass a string in place of the complex object inside a GenericParcel, behavior is as expected.

public class GenericParcel implements Parcelable {
    private Object o;

    public GenericParcel(Object in) {
        o = in;
    }

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

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeValue(o);
    }

    public Object getObject() {
        return o;
    }

    public static final Creator<GenericParcel> CREATOR = new Creator<GenericParcel>() {

        public GenericParcel createFromParcel(Parcel source) {
            return new GenericParcel(source);
        }

        public GenericParcel[] newArray(int size) {

            return new GenericParcel[size];
        }
    };

}

Upvotes: 0

Views: 289

Answers (1)

Karakuri
Karakuri

Reputation: 38595

I think your implementation of your Parcelable object is not correct. You should have a constructor that takes as its only argument a Parcel (not an Object) and you should be reading values from the Parcel in the same order you wrote them to the Parcel in writeToParcel().

public class GenericParcel implements Parcelable {
    private Object o;

    public GenericParcel(Parcel in) {
        o = in.readValue(null);
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeValue(o);
    }

    // the rest removed for brevity
}

Upvotes: 1

Related Questions