0

I'm pretty new to Android programming and I've ran into this issue.

I have an object I am trying to send into a new activity, which is an instance of this class:

public final class BusinessEntity extends com.google.api.client.json.GenericJson {

/**
 * The value may be {@code null}.
 */
@com.google.api.client.util.Key
private Contact contact;

/**
 * The value may be {@code null}.
 */
@com.google.api.client.util.Key
@com.google.api.client.json.JsonString
private java.lang.Long id;

/**
 * The value may be {@code null}.
 */
@com.google.api.client.util.Key
private java.lang.String imageUrl;

/**
 * The value may be {@code null}.
 */
@com.google.api.client.util.Key
private Person owner;

/**
 * The value may be {@code null}.
 */
@com.google.api.client.util.Key
private java.util.List<java.lang.String> tag;

/**
 * The value may be {@code null}.
 */
@com.google.api.client.util.Key
private java.lang.String type;

I have tried converting it to gson and sending it in a Bundle with the Intent, and converting it back to a BusinessEntity in the new Activity The problem is I can't deserialize it in the new activity because it contains objects of an arbitrary type. I have tried parsing it as a JsonArray, but I get the exception: "IllegalStateException: This is not a JSON Array." I guess because the object is not in a collection.

There are a lot of attributes in the Person and Contact class that I would like to be able to access in the new Activity, but I would also like to avoid sending each attribute separately.

Here's what I have in the first class:

Intent i = new Intent(mActivity, DetailsActivity.class);
Bundle b = new Bundle();
Gson gson = new Gson();
String business = gson.toJson(businesses.get(position));
b.putString("business", business); 
i.putExtras(b);
startActivity(i);

And here's what I have in the second class:

Bundle b = getIntent().getExtras();
String json = b.getString("business");

Gson gson = new Gson();
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(json).getAsJsonArray();

Contact contact = gson.fromJson(array.get(0), Contact.class);
Long id = gson.fromJson(array.get(1), Long.class);
String imageURL = gson.fromJson(array.get(2), String.class);
Person person = gson.fromJson(array.get(3), Person.class);
List<String> tag = gson.fromJson(array.get(4), List.class);

But like I said I get a IllegalStateException at

JsonArray array = parser.parse(json).getAsJsonArray();

What is a good way to do this where I don't have to send each attribute separately?

--------------------------------------EDIT-------------------------------------------------------

I tried Parcelable, Serializable, Gson, everything... I was getting errors each time trying to cast the object back into a BusinessEntity in the new activity.

The workaround I created is I made a new class called SimpleBusiness that consists of all the attributes of BusinessEntity, Contact, and Person, implements Parcelable, and takes a BusinessEntity as a parameter in its constructor. I create a new SimpleBusiness object from the BusinessEntity I went to send to the new activity, send it with the intent, and get it from the intent from the new activity. It's kind of a weird workaround but it works perfectly.

Here is the new Class:

/**
 * BusinessEntity class made with regular objects
 */
public class SimpleBusiness implements Parcelable {

    //Contact
    private String address1;
    private String address2;
    private String city;
    private long contactID;
    private String country;
    private double latitude;
    private double longitude;
    private String phones;
    private String postalCode;
    private String province;

    //BusinessEntity
    private long id;
    private String imageURL;
    private List<String> tag;
    private String type;

    //Person
    private String businessName;
    private String firstName;
    private String lastName;
    private long personId;

    /**
     * Default no-argument constructor
     */
    public SimpleBusiness(){

    }

    /**
     * Constructor taking BusinessEntity as a parameter
     * @param businessEntity
     */
    public SimpleBusiness(BusinessEntity businessEntity) {
        Contact contact = businessEntity.getContact();
        Person person = businessEntity.getOwner();

        address1 = contact.getAddress1();
        address2 = contact.getAddress2();
        city = contact.getCity();
        contactID = contact.getContactId();
        country = contact.getCountry();
        latitude = contact.getLatitude();
        longitude = contact.getLongitude();
        phones = contact.getPhones();
        postalCode = contact.getPostalCode();
        province = contact.getProvince();

        //BusinessEntity
        id = businessEntity.getId();
        imageURL = businessEntity.getImageUrl();
        tag = businessEntity.getTag();
        type = businessEntity.getType();

        //Person
        businessName = person.getBusinessName();
        firstName= person.getFirstName();
        lastName= person.getLastName();
        personId= person.getPersonId();
    }

    public String getAddress1() {
        return address1;
    }

    public void setAddress1(String address1) {
        this.address1 = address1;
    }

    public String getAddress2() {
        return address2;
    }

    public void setAddress2(String address2) {
        this.address2 = address2;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public long getContactID() {
        return contactID;
    }

    public void setContactID(long contactID) {
        this.contactID = contactID;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public double getLatitude() {
        return latitude;
    }

    public void setLatitude(double latitude) {
        this.latitude = latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    public void setLongitude(double longitude) {
        this.longitude = longitude;
    }

    public String getPhones() {
        return phones;
    }

    public void setPhones(String phones) {
        this.phones = phones;
    }

    public String getPostalCode() {
        return postalCode;
    }

    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getImageURL() {
        return imageURL;
    }

    public void setImageURL(String imageURL) {
        this.imageURL = imageURL;
    }

    public List<String> getTag() {
        return tag;
    }

    public void setTag(List<String> tag) {
        this.tag = tag;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getBusinessName() {
        return businessName;
    }

    public void setBusinessName(String businessName) {
        this.businessName = businessName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public long getPersonId() {
        return personId;
    }

    public void setPersonId(long personId) {
        this.personId = personId;
    }


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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.address1);
        dest.writeString(this.address2);
        dest.writeString(this.city);
        dest.writeLong(this.contactID);
        dest.writeString(this.country);
        dest.writeDouble(this.latitude);
        dest.writeDouble(this.longitude);
        dest.writeString(this.phones);
        dest.writeString(this.postalCode);
        dest.writeString(this.province);
        dest.writeLong(this.id);
        dest.writeString(this.imageURL);
        dest.writeList(this.tag);
        dest.writeString(this.type);
        dest.writeString(this.businessName);
        dest.writeString(this.firstName);
        dest.writeString(this.lastName);
        dest.writeLong(this.personId);
    }

    private SimpleBusiness(Parcel in) {
        this.address1 = in.readString();
        this.address2 = in.readString();
        this.city = in.readString();
        this.contactID = in.readLong();
        this.country = in.readString();
        this.latitude = in.readDouble();
        this.longitude = in.readDouble();
        this.phones = in.readString();
        this.postalCode = in.readString();
        this.province = in.readString();
        this.id = in.readLong();
        this.imageURL = in.readString();
        this.tag = new ArrayList<String>();
        in.readList(this.tag, List.class.getClassLoader());
        this.type = in.readString();
        this.businessName = in.readString();
        this.firstName = in.readString();
        this.lastName = in.readString();
        this.personId = in.readLong();
    }

    public static final Creator<SimpleBusiness> CREATOR = new Creator<SimpleBusiness>() {
        public SimpleBusiness createFromParcel(Parcel source) {
            return new SimpleBusiness(source);
        }

        public SimpleBusiness[] newArray(int size) {
            return new SimpleBusiness[size];
        }
    };
}

And the implementation:

        Intent i = new Intent(mActivity, DetailsActivity.class);
        Bundle b = new Bundle();

        BusinessEntity business = businesses.get(position);
        SimpleBusiness simpleBusiness = new SimpleBusiness(business);
        i.putExtra("business", simpleBusiness);
        //i.putExtras(b);
        startActivity(i);

And in the DetailsActivity class:

        Intent i = getIntent();
        Bundle b = i.getExtras();
        business = (SimpleBusiness)b.get("business");

Thanks for the help guys. It probably would have taken a lot longer if I didn't have the advice you guys gave me.

--------------------------------------------Edit 2--------------------------------------------

Switched to passing a BusinessEntity object directly with an EventBus. So much easier. http://www.stevenmarkford.com/passing-objects-between-android-activities/

Pass the object:

Intent i = new Intent(mActivity, DetailsActivity.class);
BusinessEntity business = businesses.get(position);
de.greenrobot.event.EventBus.getDefault().postSticky(business);
startActivity(i);

Retrieve the object: @Override

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.busEntity = (BusinessEntity) EventBus.getDefault().removeStickyEvent(BusinessEntity.class);
    setContentView(R.layout.activity_details);
}
swanhella
  • 441
  • 6
  • 14
  • its not a `JsonArray` i guess, it must be a `JsonObject` is it so ?? – Panther Oct 28 '14 at 03:52
  • Whatever you do, don't set it to a static reference :( – Matt Logan Oct 28 '14 at 04:09
  • EventBus makes your life so much easier, see the example and links in my answer to this question: http://stackoverflow.com/questions/26152755/saving-information-from-one-fragment-and-dialog-if-the-user-navigates-to-another/26153208#26153208 in essence, no need to do any serialization or anything, just put the object on the eventbus and grab it again anywhere in your code (in another Activity, Fragment, Service etc..). – cYrixmorten Oct 28 '14 at 21:28
  • Glad I could help ;) this is one of the simplest yet extremely powerful tools that I have met. Might also want to look into ButterKnife for View injection and Dagger for dependency injection of entire classes (Dagger is a bit complex at first but very neat) for example, if I need GPS positions, all I have to to in my code is to write `@Inject LocationsModule locationsModule`. All these tools can greatly decrease the lines of code and make it easier to maintain. – cYrixmorten Oct 30 '14 at 23:13
  • @cYrixmorten cool that's perfect. I quickly realized having two different classes to deal with roughly doubled my code, and the datastore I was pulling the businesses from got updated, meaning to continue using my SimpleEntity class I would have to update the entire thing, as well as the code using it. This is way more efficient. – swanhella Oct 30 '14 at 23:20
  • Just added my comment as an answer in case someone needs an answer to the same question – cYrixmorten Oct 31 '14 at 14:46

4 Answers4

0

If you are able to modify BusinessEntity, then have it implement Serializable. You may then put the business as an extra:

//To put the object as an extra
...
BusinessEntity business = businesses(get(position));
Intent intent = new Intent(mActivity, DetailsActivity.class);
intent.putExtra("business", business); // Where business is now a `Serializable`
...

//To retrieve the object (in your second class). 
//TODO -- Include check to see if intent has the extra first
BusinessEntity retrievedBusiness = (BusinessEntity) intent.getSerializableExtra("business")
akodiakson
  • 779
  • 1
  • 5
  • 10
0

You should use Parcelable Objects https://github.com/codepath/android_guides/wiki/Using-Parcelable

Yogesh Narayanan
  • 866
  • 7
  • 10
0

You can do this via Serializable interface. Just let your BusinessEntity implement Serializable, like this:

public final class BusinessEntity extends com.google.api.client.json.GenericJson implements Serializable {
     //your code here
     ...
     ...
}

Then create your intent and put an extra to it:

Intent i = new Intent(mActivity, DetailsActivity.class);
i.putExtra("BusinessEntity", yourBuisnessEntityObject);
startActivity(i);

And finally in your DetailsActivity:

BusinessEntity business = (BusinessEntity) getIntent().getSerializableExtra("BusinessEntity");

Voila! You have your BusinessEntity object in DetailsActivity.

EDIT:

Back to your code, I think the problem is that you put a JsonObject extra not a JsonArray. You should do the same things that you posted firstly, but with one correction:

JsonObject object = parser.parse(json).getAsJsonObject(); and then parse it as JsonObject by keys.

romtsn
  • 11,704
  • 2
  • 31
  • 49
  • I get a java.lang.ClassCastException: java.util.HashMap cannot be cast to _classpath_.BusinessEntity – swanhella Oct 28 '14 at 04:46
  • @swanhella in which line? – romtsn Oct 28 '14 at 04:48
  • `BusinessEntity business = (BusinessEntity)getIntent().getSerializableExtra("BusinessEntity");` – swanhella Oct 28 '14 at 04:51
  • How do you put a businessObject to the intent? Can you provide that object? – romtsn Oct 28 '14 at 04:57
  • `Intent i = new Intent(mActivity, DetailsActivity.class);` `BusinessEntity business = businesses.get(position);` `i.putExtra("BusinessEntity", business);` `startActivity(i);` – swanhella Oct 28 '14 at 05:48
  • I tried implementing Parcelable instead. That worked. I used http://www.parcelabler.com/ – swanhella Oct 28 '14 at 07:44
  • Just kidding, I keep getting null when trying to grab it in the new activity. I'll try the JsonObject. – swanhella Oct 28 '14 at 19:26
  • Same problem. I can get the JsonObject, but I can't pull any data from it. Using the parcelable method, I managed to get the data through a HashMap, but not a BusinessEntity. I'm trying to figure out how to get all the values from that but it contains some weird strings not in the BusinessEntity class -___- – swanhella Oct 28 '14 at 20:22
  • I gave up and made a new class called SimpleBusiness that is made up of all the attributes of BusinessEntity, Contact, and Person, implements Parcelable, and takes a BusinessEntity as a parameter in its constructor. I create a new SimpleBusiness object from the BusinessEntity I went to send to the new activity, send it with the intent, and get it from the intent from the new activity. It's kind of a weird workaround but it works perfectly. – swanhella Oct 28 '14 at 21:09
  • If you show me, how are you trying to pull data from JsonObject, we can make it better :) – romtsn Oct 29 '14 at 03:57
0

EventBus makes your life so much easier, see the example and links in my answer to this question: Saving information from one fragment and dialog if the user navigates to another fragment in essence, no need to do any serialization or anything, just put the object on the eventbus and grab it again anywhere in your code (in another Activity, Fragment, Service etc..)

Community
  • 1
  • 1
cYrixmorten
  • 7,110
  • 3
  • 25
  • 33