Passing multiple Objects between activities (using parcelable) - java

So what I am trying to do is pass ObjectB from the first activity to the second. ObjectB contains another object, ObjectA. I am getting really confused as to how to implement this. Also, I am using a list in ObjectA because I am going to have multiple integer values instead of just the 1 in this example. Here is the first activity:
private ObjectB objB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
objB = new ObjectB();
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra("KEY", objB);
startActivity(intent);
}
and the second activity:
private ObjectB objB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
objB = new ObjectB();
TextView tv = (TextView) findViewById(R.id.TextView1);
Bundle b = getIntent().getExtras();
objB = b.getParcelable("KEY");
tv.setText(objB.obj.stage1Count);
}
Class for ObjectB:
public class ObjectB implements Parcelable{
public ObjectA obj;
public ObjectB() { obj = new ObjectA(); }
public ObjectA getObj() {
return obj;
}
public ObjectB(Parcel in) {
readFromParcel(in);
}
public void setObj(ObjectA obj) {
this.obj = obj;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(obj, flags);
}
private void readFromParcel(Parcel in) {
obj = in.readParcelable(ObjectA.class.getClassLoader());
}
public static final Parcelable.Creator CREATOR =
new Parcelable.Creator() {
public ObjectB createFromParcel(Parcel in) {
return new ObjectB(in);
}
public ObjectB[] newArray(int size) {
return new ObjectB[size];
}
};
}
Class for ObjectA:
public class ObjectA implements Parcelable{
public int stage1Count = 1;
public ObjectA() { ; };
public ObjectA(Parcel in) {
readFromParcel(in);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
List<Integer> iList = new ArrayList<Integer>();
iList.add(stage1Count);
dest.writeList(iList);
}
private void readFromParcel(Parcel in) {
List<Integer> iList = new ArrayList<Integer>();
iList = in.readArrayList(Integer.class.getClassLoader());
stage1Count = iList.get(0);
}
public static final Parcelable.Creator CREATOR =
new Parcelable.Creator() {
public ObjectA createFromParcel(Parcel in) {
return new ObjectA(in);
}
public ObjectA[] newArray(int size) {
return new ObjectA[size];
}
};
}

Try this in first activity:
List<ObjectB> list = new ArrayList<ObjectB>;
intent.putParcelableArrayListExtra("key", list);
And in second activity
List<ObjectB> list = new ArrayList<ObjectB>;
list = bundle.getParcelableArrayList("key");
From list get your objectB

This was a really dumb question but I figured it out after a really long time haha. The problem is tv.setText(objB.obj.stage1Count);because objB.obj.stage1Count is actually an integer but for some reason it does not ring any bells when you try to use it as a string, idk maybe its something with the parceing.

Related

Utilising Parcelable to send Array across two activities

I'm trying to send a populated array of a created class called 'Exercise' between two activities, and I've read the best way to do so I utilising the Parcelable class.
Activity 2 crashes whenever it starts. I've followed tutorials online for this and this is how they treat the sending of the data.
Exercise Class:
import android.os.Parcel;
import android.os.Parcelable;
public class Exercise implements Parcelable {
public String Name = "";
public int Time = 0;
public boolean SwitchDirection = false;
Exercise(String n, int l, boolean s){
Name = n;
Time = l;
SwitchDirection = s;
}
protected Exercise(Parcel in) {
Name = in.readString();
Time = in.readInt();
SwitchDirection = in.readByte() != 0;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(Name);
dest.writeInt(Time);
dest.writeByte((byte) (SwitchDirection ? 1 : 0));
}
public static final Creator<Exercise> CREATOR = new Creator<Exercise>() {
#Override
public Exercise createFromParcel(Parcel in) {
return new Exercise(in);
}
#Override
public Exercise[] newArray(int size) {
return new Exercise[size];
}
};
}
Activity 1:
Exercise[] Exercises = new Exercise[]{
new Exercise("Scisssors", 60, false),
new Exercise("Cross Knee Planks", 60, false),
new Exercise("Twisting Pistons", 30, false),
new Exercise("Accordion Crunches", 60, true),
new Exercise("Canoe Crunch", 30, false),
new Exercise("Upper Circle Crunches", 30, true)
};
Intent i = new Intent(this, Activity2.class);
i.putExtra("Exercises", Exercises);
startActivity(i);
Activity 2:
Exercise[] Exercises;
Exercises = (Exercise[]) getIntent().getParcelableArrayExtra("Exercises");
I think you don't should send and get an array of Parcelable. You should give an array for Parcelable, and get it in Activity 2.
I have an example that send a HashMap between 2 activities.
public class BaseData implements Parcelable {
protected HashMap<String, Object> mData;
public BaseData(HashMap<String, Object> data) {
mData = data;
}
protected BaseData(Parcel in) {
try {
mData = in.readHashMap(HashMap.class.getClassLoader());
} catch (Exception e) {
e.printStackTrace();
}
}
public static final Creator<BaseData> CREATOR = new Creator<BaseData>() {
#Override
public BaseData createFromParcel(Parcel in) {
return new BaseData(in);
}
#Override
public BaseData[] newArray(int size) {
return new BaseData[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
try {
if (null == mData) {
return;
}
dest.writeValue(mData);
} catch (Exception e) {
}
}
public HashMap<String, Object> getData() {
return mData;
}
}
In Activty 1 you will send data like that:
HashMap<String, Object> hm = new HashMap<>();
hm.put("data_1", array_data_1);
hm.put("data_2",array_data_2);
BaseData baseData = new BaseData(hm);
BaseData baseData = new BaseData(data);
Bundle bundle = new Bundle();
bundle.putParcelable("base_data", baseData);
Intent intent = new Intent(context,Activity2.class)
intent.putExtra("data",bundle);
In Activy 2 you will receive a bundle, then get basedata from bundle and get HashMap from basedata.
Bundle bundle = getIntent().getBundleExtra("data");
BaseData baseData = bundle.getParcelable("base_data");
HashMap<String,Object> hm = baseData.getData();
You can replace HashMap by Array. If you can't implement it, please tell me I will send you a complete example.

Passing an arraylist of arraylists

I know it's a commonly asked question and I looked at the solutions online, but I am having a difficulty implementing this on my own.
I have a class which contains three variables: Location, Date and Uri.
I have an Arraylist which consists of multiple Arraylists that contains said class.
For instance:
ArrayList<ArrayList<class>>
I am trying to pass this onto another activity, yet unsuccessful.
I tried both Parcelable and Serializable but none worked.
Edit: Source code added.
Class documentation:
public class imageHolder implements Parcelable
{
private Uri uri;
private Date date;
private Location loc;
public imageHolder(Uri uriAdd, Date dateAdded,Location imgLoc)
{
this.uri = uriAdd;
this.date = dateAdded;
this.loc = imgLoc;
}
public static final Creator<imageHolder> CREATOR = new Creator<imageHolder>() {
#Override
public imageHolder createFromParcel(Parcel in) {
return new imageHolder(in);
}
#Override
public imageHolder[] newArray(int size) {
return new imageHolder[size];
}
};
public Uri getURI() { return this.uri; }
public Date getDate() {return this.date; }
public Location getLocation() {return this.loc; };
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeSerializable(date);
parcel.writeParcelable(uri,i);
parcel.writeParcelable(loc, i);
}
protected imageHolder(Parcel in) {
date = (java.util.Date) in.readSerializable();
uri = in.readParcelable(Uri.class.getClassLoader());
loc = in.readParcelable(Location.class.getClassLoader());
}
}
First activity:
ArrayList<ArrayList<imageHolder>> sepImages = new ArrayList<ArrayList<imageHolder>>();
sepImages = groupPics(images);
Intent nextActivity = new Intent(loadImages.this, storiesScreen.class);
nextActivity.putExtra("images",images);
startActivity(nextActivity);
finishActivity(0);
Second activity:
ArrayList<ArrayList<imageHolder>> sepImages =
(ArrayList<ArrayList<imageHolder>>) getIntent().getParcelableExtra("images");
Log.d("stories","test");
I think the best thing to do here would be to create a new class that implements Parcelable and pass instances of this new class between activities.
public class ParcelableListOfLists implements Parcelable {
private ArrayList<ArrayList<imageHolder>> listOfLists;
public ParcelableListOfLists(ArrayList<ArrayList<imageHolder>> listOfLists) {
this.listOfLists = listOfLists;
}
public ArrayList<ArrayList<imageHolder>> getListOfLists() {
return listOfLists;
}
// parcelable implementation here
}
Once you have this class, you can be in full control of how your data is parceled, and that lets you do some things that you won't be able to do with the Android built-in offerings.
Here's one way you could parcel a list of lists:
#Override
public void writeToParcel(Parcel dest, int flags) {
if (listOfLists != null) {
dest.writeInt(listOfLists.size());
for (ArrayList<imageHolder> list : listOfLists) {
dest.writeTypedList(list);
}
} else {
dest.writeInt(-1);
}
}
And on the other side, you can recreate the list of lists like this:
public ParcelableListOfLists(Parcel in) {
int size = in.readInt();
if (size != -1) {
this.listOfLists = new ArrayList<>(size);
for (int i = 0; i < size; ++i) {
ArrayList<imageHolder> list = in.createTypedArrayList(imageHolder.CREATOR);
listOfLists.add(list);
}
} else {
this.listOfLists = null;
}
}
With all of this together, you can pass your list of lists between activities like this:
Intent nextActivity = new Intent(loadImages.this, storiesScreen.class);
nextActivity.putExtra("images", new ParcelableListOfLists(images));
startActivity(nextActivity);
and retrieve them in the next activity like this:
ParcelableListOfLists plol = getIntent().getParcelableExtra("images");
ArrayList<ArrayList<imageHolder>> images = plol.getListOfLists();
I think that you can use Gson too.
In your build.gradle
implementation 'com.google.code.gson:gson:2.8.4'
In the first activity
Gson gson = new Gson();
String json = gson.toJson(yourObject);
intent.putExtra("yourKey", json);
In the second activity
Gson gson = new Gson();
YourObject yourObject = gson.fromJson(getIntent().getStringExtra("yourKey"), YourObject.class);
Easy and fast.
Ok.
Your Model
public class ImageHolder implements Serializable {
// Use String here, to avoid serialization problems
private String uri;
private Date date;
private Location loc;
public ImageHolder() {
}
public ImageHolder(String uri, Date date, Location loc) {
this.uri = uri;
this.date = date;
this.loc = loc;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Location getLoc() {
return loc;
}
public void setLoc(Location loc) {
this.loc = loc;
}
#Override
public String toString() {
return "ImageHolder{" +
"uri=" + uri +
", date=" + date +
", loc=" + loc +
'}';
}
}
Create a Container class
public class Container implements Serializable {
private ArrayList<ImageHolder> list;
public Container() {
}
public Container(ArrayList<ImageHolder> list) {
this.list = list;
}
public ArrayList<ImageHolder> getList() {
return list;
}
public void setList(ArrayList<ImageHolder> list) {
this.list = list;
}
#Override
public String toString() {
return "Container{" +
"list=" + list +
'}';
}
}
Your First Activity
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
#Override
protected void onPostCreate(#Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
ImageHolder imageHolder0 = new ImageHolder("http://www.stackoverflow.com", new Date(), new Location("test0"));
ImageHolder imageHolder1 = new ImageHolder("http://www.google.com", new Date(), new Location("test1"));
ArrayList<ImageHolder> list = new ArrayList<>();
list.add(imageHolder0);
list.add(imageHolder1);
Container container = new Container(list);
Gson gson = new Gson();
String json = gson.toJson(container);
Intent intent = new Intent(MainActivity.this, TestActivity.class);
intent.putExtra("yourKey", json);
startActivity(intent);
}
}
Your second activity
public class TestActivity extends AppCompatActivity {
public static final String TAG = TestActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onPostCreate(#Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
Gson gson = new Gson();
Container container = gson.fromJson(getIntent().getStringExtra("yourKey"), Container.class);
Log.d(TAG, "OK?" + container.getList().toString());
// Here convert String uri Fields to Uri Objects
// Example:
Uri uri = Uri.parse(container.getList().get(0).getUri());
}
}
Logcat result: 08-01 11:10:22.097 6671-6671/it.darksurfer.english.template D/TestActivity: OK?[ImageHolder{uri=http://www.stackoverflow.com, date=Wed Aug 01 11:10:21 GMT+02:00 2018, loc=Location[test0 0,000000,0,000000 acc=??? t=?!? et=?!?]}, ImageHolder{uri=http://www.google.com, date=Wed Aug 01 11:10:21 GMT+02:00 2018, loc=Location[test1 0,000000,0,000000 acc=??? t=?!? et=?!?]}]
Obviously you can put an undefined number of others ArrayList in the list of Container class!

Extended (custom) arrayList of custom objects parcelable return size 0

It's one day work with no solution,
I would to passed data beetween activity, I implement Parcelable but from called activity I receive the ListFileMedia with a size=0.
When I mistake?
Class ListFileMedia (Extended of ArrayList)
public class ListFileMedia extends ArrayList<FileMedia> implements Parcelable{
public ListFileMedia(){.....}
// for test i have cancel all methods and var, sure i tested also with...
//Interface Parcelable
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
//dest.writeInt(countIntestazioni);
// Add inner class
dest.writeParcelable(this.add(FileMedia),flags);
}
public ListFileMedia(Parcel in) {
}
public final static Parcelable.Creator <ListFileMedia>CREATOR = new Creator<ListFileMedia>() {
#Override
public ListFileMedia createFromParcel(Parcel source) {
return new ListFileMedia(source);
}
#Override
public ListFileMedia[] newArray(int size) {
return new ListFileMedia[size];
}
};
}
Custom objects in FileListMedia
public class FileMedia implements Comparable,Parcelable{
public String getPath() {return path;}
public String getBucket() {
return bucket;
}
public String getMimeType() { return mimeType; }
private String path;
private String bucket;
private String mimeType;
private int giorno;
private int mese;
private int anno;
public FileMedia(int giorno,int mese,int anno, String path,String bucket,String mimeType){
....
}
public int compareTo(Object o) {
.....
}
//Interface Parcelable
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.path);
dest.writeString(this.bucket);
dest.writeString(this.mimeType);
dest.writeInt(this.giorno);
dest.writeInt(this.mese);
dest.writeInt(this.anno);
}
public FileMedia(Parcel in) {
this.path = in.readString();
this.bucket=in.readString();
this.mimeType=in.readString();
this.giorno=in.readInt();
this.mese=in.readInt();
this.anno=in.readInt();
}
public final static Parcelable.Creator <FileMedia>CREATOR = new Creator<FileMedia>() {
#Override
public FileMedia createFromParcel(Parcel source) {
return new FileMedia(source);
}
#Override
public FileMedia[] newArray(int size) {
return new FileMedia[size];
}
};}
Call activity
ListFileMedia test=new ListFileMedia();
ArrayList arrayList=new ArrayList();
test.add(new FileMedia(10,12,2016,"t","t","t"));
b.putParcelable("list",test);
intent.putExtras(b);
startActivity(intent);
Called activity
Intent intent = this.getIntent();
Bundle b=intent.getExtras();
ListFileMedia listFileMedia (ListFileMedia)b.getParcelable("list"); //size==0 !!!
But if i passed only b.putParcelable("list",new FileMedia(10,12,2016,"t","t","t") work correctely!!
Sorry for my English..

Multiple putextra Unmarshalling unknown type code

I want to pass a custom object between my activities. I implemented Parceable for this class and put it in a extra. It works like a charm. Except if I put some other extras. In this case the app crash with this error : Unmarshalling unknown type code.
I have 2 class : A and B. A has a private field B. et my class B has a nested enum Enum. I implemented Parceable for A, B and Enum.
There is my code, I have rewritten it to be more concise.
A.java
public class A implements Parcelable {
B objectB;
String myString;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(myString);
out.writeParcelable(objectB, flags);
}
public static final Parcelable.Creator<Adresse> CREATOR = new Parcelable.Creator<Adresse>() {
public A createFromParcel(Parcel in) {
return new Adresse(in);
}
public A[] newArray(int size) {
return new A[size];
}
};
private Adresse(Parcel in) {
myString = in.readString();
objectB = in.readParcelable(B.class.getClassLoader());
}
}
B.java
public class B implements Parceable {
Bitmap bitmap;
String otherString;
Enum enum;
public enum Enum implements Parceable {
ONE ("One")
TWO ("Two")
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(ONE.name);
out.writeString(TWO.name);
}
public static final Parcelable.Creator<Identifiant> CREATOR = new Parcelable.Creator<Enum>() {
public Enum createFromParcel(Parcel in) {
return Enum.values()[in.readInt()];
}
public Enum[] newArray(int size) {
return new Enum[size];
}
};
}
public B(Parcel in) {
readFromParcel(in);
}
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(otherString);
out.writeParcelable(bitmap, flags);
out.writeParcelable(enum, flags);
}
private void readFromParcel(Parcel in) {
otherString = in.readString();
bitmap = in.readParcelable(Bitmap.class.getClassLoader());
enum = in.readParcelable(Enum.class.getClassLoader());
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public B createFromParcel(Parcel in) {
return new B(in);
}
public B[] newArray(int size) {
return new B[size];
}
};
#Override
public int describeContents() {
return 0;
}
MyActivity.java
Intent intent = new Intent(A.this, B.class);
Bundle bundle = new Bundle();
A objectA = new A();
bundle.putParcelable("A", a);
bundle.putInt("Int", 1); //If I comment this line it works
intent.putExtras(bundle);
startActivityForResult(intent, 1);

BadParcelableException: Launcher shortcut

I'm trying to pass in a custom Object into a shortcut I'm installing on the home screen, but I'm receiving a BadParcelableException when as soon as the shortcut is created. I've tried calling Bundle.setClassLoader, but the error persists.
Is there just a limitation with launchers that support home screen shortcuts?
public class Foo implements Parcelable {
public String title;
private Foo(Parcel in) {
title = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
}
public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>() {
#Override
public Foo createFromParcel(Parcel in) {
return new Foo(in);
}
#Override
public Foo[] newArray(int size) {
return new Foo[size];
}
};
}
public static void installShortcut(Context context, Foo foo) {
final Bundle args = new Bundle();
args.setClassLoader(Foo.class.getClassLoader());
args.putParcelable(EXTRA_FOO, foo);
final Intent detail = new Intent(context, FooActivity.class);
detail.putExtras(args);
final Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, detail);
...
context.sendBroadcast(shortcut);
}

Categories

Resources