How to send objects through bundle

AndroidSerializationAndroid ActivityBundleParcelable

Android Problem Overview


I need to pass a reference to the class that does the majority of my processing through a bundle.

The problem is it has nothing to do with intents or contexts and has a large amount of non-primitive objects. How do I package the class into a parcelable/serializable and pass it to a startActivityForResult?

Android Solutions


Solution 1 - Android

You can also use Gson to convert an object to a JSONObject and pass it on bundle. For me was the most elegant way I found to do this. I haven't tested how it affects performance.

In Initial Activity

Intent activity = new Intent(MyActivity.this,NextActivity.class);
activity.putExtra("myObject", new Gson().toJson(myobject));
startActivity(activity);

In Next Activity

String jsonMyObject;
Bundle extras = getIntent().getExtras();
if (extras != null) {
   jsonMyObject = extras.getString("myObject");
}
MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);

Solution 2 - Android

Figuring out what path to take requires answering not only CommonsWare's key question of "why" but also the question of "to what?" are you passing it.

The reality is that the only thing that can go through bundles is plain data - everything else is based on interpretations of what that data means or points to. You can't literally pass an object, but what you can do is one of three things:

  1. You can break the object down to its constitute data, and if what's on the other end has knowledge of the same sort of object, it can assemble a clone from the serialized data. That's how most of the common types pass through bundles.

  2. You can pass an opaque handle. If you are passing it within the same context (though one might ask why bother) that will be a handle you can invoke or dereference. But if you pass it through Binder to a different context it's literal value will be an arbitrary number (in fact, these arbitrary numbers count sequentially from startup). You can't do anything but keep track of it, until you pass it back to the original context which will cause Binder to transform it back into the original handle, making it useful again.

  3. You can pass a magic handle, such as a file descriptor or reference to certain os/platform objects, and if you set the right flags Binder will create a clone pointing to the same resource for the recipient, which can actually be used on the other end. But this only works for a very few types of objects.

Most likely, you are either passing your class just so the other end can keep track of it and give it back to you later, or you are passing it to a context where a clone can be created from serialized constituent data... or else you are trying to do something that just isn't going to work and you need to rethink the whole approach.

Solution 3 - Android

The Parcelable interface is a good way to pass an object with an Intent.

https://stackoverflow.com/questions/7181526/example-of-implementing-parcelable is a pretty good answer on how to use Parcelable

The official google docs also include an example

Solution 4 - Android

You could use the global application state.

Update:

Customize and then add this to your AndroidManifest.xml :

<application android:label="@string/app_name" android:debuggable="true" android:name=".CustomApplication"

And then have a class in your project like this :

package com.example;

import android.app.Application;

public class CustomApplication extends Application {
    public int someVariable = -1;
}

And because "It can be accessed via getApplication() from any Activity or Service", you use it like this:

CustomApplication application = (CustomApplication)getApplication();
application.someVariable = 123; 

Hope that helps.

Solution 5 - Android

You can also make your objects Serializable and use the Bundle's getSerializable and putSerializable methods.

Solution 6 - Android

Possible solution:

Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());

Class CustomObject:

class CustomObject implements Serializable{
 private SubCustomObject1 sc1;
 private SubCustomObject2 sc2;
}

Subcustom objects:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }

Solution 7 - Android

One More way to send objects through bundle is by using bundle.putByteArray
Sample code

public class DataBean implements Serializable {
private Date currentTime;

public setDate() {
    currentTime = Calendar.getInstance().getTime();
 }

public Date getCurrentTime() {
    return currentTime;
 }
}

put Object of DataBean in to Bundle:

class FirstClass{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//When you want to start new Activity...
Intent dataIntent =new Intent(FirstClass.this, SecondClass.class);
			Bundle dataBundle=new Bundle();
            DataBean dataObj=new DataBean();
            dataObj.setDate();
			try {
				dataBundle.putByteArray("Obj_byte_array", object2Bytes(dataObj));
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				
			}
			
			dataIntent.putExtras(dataBundle);
			
			startActivity(dataIntent);
}

Converting objects to byte arrays

/**
 * Converting objects to byte arrays
 */
static public byte[] object2Bytes( Object o ) throws IOException {
	  ByteArrayOutputStream baos = new ByteArrayOutputStream();
	  ObjectOutputStream oos = new ObjectOutputStream( baos );
	  oos.writeObject( o );
	  return baos.toByteArray();
	}

Get Object back from Bundle:

class SecondClass{
DataBean dataBean;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//Get Info from Bundle...
    Bundle infoBundle=getIntent().getExtras();
	try {
		dataBean = (DataBean)bytes2Object(infoBundle.getByteArray("Obj_byte_array"));
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

Method to get objects from byte arrays:

/**
 * Converting byte arrays to objects
 */
static public Object bytes2Object( byte raw[] )
	    throws IOException, ClassNotFoundException {
	  ByteArrayInputStream bais = new ByteArrayInputStream( raw );
	  ObjectInputStream ois = new ObjectInputStream( bais );
	  Object o = ois.readObject();
	  return o;
	}

Hope this will help to other buddies.

Solution 8 - Android

1.A very direct and easy to use example, make object to be passed implement Serializable.

class Object implements Serializable{
    String firstName;
   String lastName;
}

2.pass object in bundle

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);

3.get passed object from bundle as Serializable then cast to Object.

Object object = (Object) getArguments().getSerializable("object");

Solution 9 - Android

I came across this question when I was looking for a way to pass a Date object. In my case, as was suggested among the answers, I used Bundle.putSerializable() but that wouldn't work for a complex thing as the described DataManager in the original post.

My suggestion that will give a very similar result to putting said DataManager in the Application or make it a Singleton is to use Dependency Injection and bind the DataManager to a Singleton scope and inject the DataManager wherever it is needed. Not only do you get the benefit of increased testability but you'll also get cleaner code without all of the boiler plate "passing dependencies around between classes and activities" code. (Robo)Guice is very easy to work with and the new Dagger framework looks promising as well.

Solution 10 - Android

This is a very belated answer to my own question, but it keep getting attention, so I feel I must address it. Most of these answers are correct and handle the job perfectly. However, it depends on the needs of the application. This answer will be used to describe two solutions to this problem.

Application

The first is the http://developer.android.com/reference/android/app/Application.html">Application</a>;, as it has been the most spoken about answer here. The application is a good object to place entities that need a reference to a Context. A ServerSocket undoubtedly would need a context (for file I/o or simple ListAdapter updates). I, personally, prefer this route. I like application's, they are useful for context retrieving (because they can be made static and not likely cause a memory leak) and have a simple lifecycle.

Service

The http://developer.android.com/guide/components/services.html">Service`</a> is second. A Serviceis actually the better choice for my problem becuase that is what services are designed to do:
A Service is an application component that can perform long-running operations in
the background and does not provide a user interface.
Services are neat in that they have a more defined lifecycle that is easier to control. Further, if needed, services can run externally of the application (ie. on boot). This can be necessary for some apps or just a neat feature.

This wasn't a full description of either, but I left links to the docs for those who want to investigate more. Overall the Service is the better for the instance I needed - running a ServerSocket to my SPP device.

Solution 11 - Android

another simple way to pass object using a bundle:

  • in the class object, create a static list or another data structure with a key
  • when you create the object, put it in the list/data structure with the key (es. the long timestamp when the object is created)
  • create the method static getObject(long key) to get the object from the list
  • in the bundle pass the key, so you can get the object later from another point in the code

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionahodderView Question on Stackoverflow
Solution 1 - AndroidLaranjeiroView Answer on Stackoverflow
Solution 2 - AndroidChris StrattonView Answer on Stackoverflow
Solution 3 - AndroidchrisView Answer on Stackoverflow
Solution 4 - AndroidNeilView Answer on Stackoverflow
Solution 5 - Androiddhaag23View Answer on Stackoverflow
Solution 6 - AndroidPraKharView Answer on Stackoverflow
Solution 7 - AndroidRupesh YadavView Answer on Stackoverflow
Solution 8 - Androidknig_TView Answer on Stackoverflow
Solution 9 - AndroidbritzlView Answer on Stackoverflow
Solution 10 - AndroidahodderView Answer on Stackoverflow
Solution 11 - AndroidshaolinView Answer on Stackoverflow