I want to send an object from one Details Activity to Persons Activity. I followed the tutorials but I get the following error:
12-19 08:19:00.434: E/AndroidRuntime(1011): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.workingonlist/com.example.workingonlist.Persons}: android.os.BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called CREATOR on class com.example.workingonlist.Person
Here is the Person model:
public class Person implements Parcelable {
private String name;
private String surname;
private String gender;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(Parcel in){
name= in.readString();
surname= in.readString();
gender= in.readString();
}
public Person(String name,String surname,String gender){
this.name=name;
this.surname=surname;
this.gender=gender;
}
// getters and setters
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(surname);
dest.writeString(gender);
}
private Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
#Override
public Person createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new Person(source);
}
#Override
public Person[] newArray(int size) {
// TODO Auto-generated method stub
return new Person[size];
}
};
}
This is Details Activity which I want to send Person object.
private View.OnClickListener onClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v.getId()==btn_save.getId()){
Person p = new Person();
p.setName(et_name.getText().toString());
p.setSurname(et_surname.getText().toString());
switch(rg.getCheckedRadioButtonId()){
case R.id.button1:{
p.setGender("Male");
break;
}
case R.id.button2:{
p.setGender("Female");
break;
}
}
Intent i = new Intent(Details.this,Persons.class);
i.putExtra("person",p);
startActivity(i);
}
}
};
And here is the Persons Activity which I want to get Person object.
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
PersonAdapter adapter = new PersonAdapter();
setContentView(R.layout.persons);
Bundle b = getIntent().getExtras();
if (b != null) {
Person p = b.getParcelable("person");
adapter.add(p);
}
setListAdapter(adapter);
}
What can I do in order to solve this problem ? Any help is appreciated.Thanks in advance.
You need to set your CREATOR public static final:
public static final Parcelable.Creator CREATOR = new Parcelable.Creator()
Look at this tutorials which deals with your issue
public static final Parcelable.Creator CREATOR =
new Parcelable.Creator() {
public Person createFromParcel(Parcel in) {
return new Person(in);
}
public Person[] newArray(int size) {
return new Person[size];
}
};
http://shri.blog.kraya.co.uk/2010/04/26/android-parcel-data-to-pass-between-activities-using-parcelable-classes/
For some reason I can't add a comment to Festus Tamakloe's answer, but I just wanted to add that this helped me. I was following some tutorials which was using the static creator. I didn't have "public" on it!
So make sure you have public on it.
Related
I am trying to pass a custom object from one activity to another one.
I found that we can use a bundle to pass data into the intent and that we need a parcelable interface implemented in our class.
In the following code I removed the useless stuff.
public class TravelCard implements Parcelable {
public static final Creator<TravelCard> CREATOR = new Creator<TravelCard>() {
#Override
public TravelCard createFromParcel(Parcel in) {
return new TravelCard(in);
}
#Override
public TravelCard[] newArray(int size) {
return new TravelCard[size];
}
};
private String travelTitle, travelCountry, dateRange, numOfPerson;
private List<TravelDay> days;
protected TravelCard(Parcel in) {
travelTitle = in.readString();
travelCountry = in.readString();
dateRange = in.readString();
numOfPerson = in.readString();
in.readTypedList(days, TravelDay.CREATOR);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.travelTitle);
dest.writeString(this.travelCountry);
dest.writeString(this.dateRange);
dest.writeString(this.numOfPerson);
dest.writeTypedList(this.days);
}
In this class I have a List of another custom object:
public class TravelDay implements Parcelable {
public static final Creator<TravelDay> CREATOR = new Creator<TravelDay>() {
#Override
public TravelDay createFromParcel(Parcel in) {
return new TravelDay(in);
}
#Override
public TravelDay[] newArray(int size) {
return new TravelDay[size];
}
};
public int current_day;
private String title, note, dateOfToday;
protected TravelDay(Parcel in) {
title = in.readString();
note = in.readString();
dateOfToday = in.readString();
current_day = in.readInt();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(note);
dest.writeString(dateOfToday);
dest.writeInt(current_day);
}
I think until here everything should be fine.
In my activity :
Intent intent = new Intent(MainActivity.this, TravelDayActivity.class);
Bundle data = new Bundle();
data.putParcelable(DataKey.TRAVEL_CARD_BUNDLE,item);
intent.putExtras(data);
startActivity(intent);
And then in the TravelDayActivity :
Intent intent = getIntent();
Bundle data = intent.getExtras();
TravelCard travelCard = data.getParcelable(DataKey.TRAVEL_CARD_BUNDLE);
Every time I tried to access the TravelDayActivity the app stop running.
I used the debug mode to search something wrong but I did not find anything.
Thank you in advance
EDIT :
In the MainActivity that's how I get the item variable:
mAdapter = new TravelCardAdapter(travelCards, new TravelCardAdapter.OnItemClickListener() {
#Override
public void onItemClick(TravelCard item) {
Intent intent = new Intent(MainActivity.this,TravelDayActivity.class);
Bundle data = new Bundle();
data.putParcelable(DataKey.TRAVEL_CARD_BUNDLE,item);
intent.putExtras(data);
startActivity(intent);
}
});
Whenever I click on one of the recycler view item this code above is executed.
After the suggestion of #BVantur, I solved my problem using the parceler library :
parceler library
It has been very helpful, easy to use and a good documentation! I highly recommend it.
When I'm trying to pass an intent from one activity to another my app crashes, without the putExtra() it works fine.
Here's my snippet from the first activity
ArrayList<Subject> subjectList = new ArrayList<Subject>();
public void computeGrades(View view){
Intent intent = new Intent(this, JLCSActivity2B.class);
intent.putExtra("subjectList", subjectList);
startActivity(intent);
}
The Second Activity
public class JLCSActivity2B extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
Intent intent = getIntent();
ArrayList<Subject> subjectList = (ArrayList<Subject>) intent.getSerializableExtra("subjectList");
}
}
You need to implement Serializable in your Subject class.
public class Subject implements Serializable {
//your variables, constructor and getters and setters
}
In your Source Activity, use this :
ArrayList<Subject> subjectList = new ArrayList<Subject>();
Intent intent = new Intent(SourceActivity.this, TargetActivity.class);
intent.putExtra("subjectList", subjectList);
In your Target Activity, use this :
ArrayList<Subject> subjectList = new ArrayList<Subject>();
subjectList = (ArrayList<Question>)getIntent().getSerializableExtra("subjectList");
I hope it helps!
Implement your Subject class with Parcelable or Serializable
Android does not allow to pass objects between activities unless they implement Parcelable or Serializable. The fact that Parcelable is faster than Serialization makes it a preferred choice of approach while passing an object.
Example implementing Parcelable - http://wptrafficanalyzer.in/blog/android-parcelable-example-passing-data-between-activities/
Parcelable Vs Serializable - http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
You can extend your entity class with serializable or better than seriablizable with parcelable interface.
You should implement parcelable interface in your Subject entity
public class Subject implements Parcelable {
String parceldata;
// your other fields with getter & setters
public Subject(Parcel in) {
String[] data = new String[1];
in.readStringArray(data);
this.parceldata = data[0];
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Subject createFromParcel(Parcel in) {
return new Subject(in);
}
public Subject[] newArray(int size) {
return new Subject[size];
}
};
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
}
}
for sending
args.putParcelable("data", subjectlist);
and to access
subjectlist = (ArrayList<Subject>) getArguments().getParcelable("data");
hope this will help you..
I'm fairly new to java/android. I am attempting to pass a custom object (Raffle), which is implementing Parcelable, to another activity.
In the receiving activity I am able to access string properties of this object, but lists appear to be emptied at some point. Toasting the the list.size() in the first activity gives 3, but the same toast in the receiving activity gives 0.
Relevant code is below. Please let me know if I have left out anything.
onCLickListener in Sending Activity (HomeActivity)
raffleListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Intent intent = new Intent(HomeActivity.this,RafflePurchaseActivity.class);
Raffle selectedRaffle = (Raffle) allRaffles.get(position);
Toast.makeText(getApplicationContext(), "1: " + selectedRaffle.Description + ": " + Integer.toString(selectedRaffle.getTicketTiers().size()), Toast.LENGTH_SHORT).show();
//Toast.makeText(getApplicationContext(), "TEST: " + Integer.toString(selectedRaffle.ticketTiers.size()), Toast.LENGTH_SHORT).show();
intent.putExtra("raffle", selectedRaffle);
startActivity(intent);
}
});
Receiving Activity (RafflePurchaseActivity)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_raffle_purchase);
Bundle bundle = this.getIntent().getExtras();
Raffle theRaffle = bundle.getParcelable("raffle");
List<RaffleTicketTier> xticketTiers = theRaffle.getTicketTiers();
Toast.makeText(getApplicationContext(), "2:" + theRaffle.Description + ": " + Integer.toString(xticketTiers.size()), Toast.LENGTH_SHORT).show();
}
the Raffle class
public class Raffle implements Parcelable {
public String Title;
public String Description;
public int TicketLimit;
public int numPrizes;
public String prize1;
public String prize2;
public String prize3;
public String prize4;
private List<RaffleTicketTier> ticketTiers = new ArrayList<RaffleTicketTier>();
public Raffle() {
Title = "Art Union";
Description = "THIS IS A RAFFLE DESCRIPTION";
ticketTiers.add(new RaffleTicketTier(1,10.00));
ticketTiers.add(new RaffleTicketTier(3,20.00));
ticketTiers.add(new RaffleTicketTier(8,50.00));
ticketTiers.add(new RaffleTicketTier(15,100.00));
testList.add("Test1");
testList.add("Test2");
testList.add("Test3");
}
//================================================================================
// Getters/Setters
//================================================================================
public List<RaffleTicketTier> getTicketTiers() {
return ticketTiers;
}
//================================================================================
// Parcelable methods
//================================================================================
//Constructor to use when re-constructing object from a parcel
public Raffle(Parcel in) {
readFromParcel(in);
}
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(Title);
dest.writeString(Description);
dest.writeInt(TicketLimit);
dest.writeInt(numPrizes);
dest.writeString(prize1);
dest.writeString(prize2);
dest.writeString(prize3);
dest.writeString(prize4);
}
private void readFromParcel(Parcel in) {
Title= in.readString();
Description= in.readString();
TicketLimit= in.readInt();
numPrizes= in.readInt();
prize1= in.readString();
prize2= in.readString();
prize3= in.readString();
prize4= in.readString();
}
public static final Parcelable.Creator<Raffle> CREATOR = new Parcelable.Creator<Raffle>() {
public Raffle createFromParcel(Parcel in) {
return new Raffle(in);
}
public Raffle[] newArray(int size) {
return new Raffle[size];
}
};
}
You don't seem to be writing tickerTiers to the parcel. Something like this answer https://stackoverflow.com/a/10781119/156708 for parceling arrays of custom types.
Relevant code from other answer
public void writeToParcel(Parcel out, int arg1) {
out.writeInt(mObjList.length);
out.writeTypedArray(mObjList, arg1);
}
private void readFromParcel(Parcel in) {
int size = in.readInt();
mObjList = in.readTypedArray(new MyClass[size], MyClass.CREATOR);
}
I use 2 intent in same activity.One of them for take input Firstname,Lastname and Id.Other intent for send data to another activity.
But when I use intents like that code didn't work.
Can I use intents like that
intent.putExtra("lastName", intent2.getString("lastName"));
Search Activity
Intent intent = new Intent(getApplicationContext(),SearchActivity.class);
Bundle b=new Bundle();
b.putString("firstName", firstName);
b.putString("lastName", lastName);
b.putString("id", id);
b.putParcelable("LoginPartClass",lp2);
intent.putExtras(b);
startActivity(intent);
Search Activity code
final Bundle intent2 = getIntent().getExtras();
Intent intent = new Intent(getApplicationContext(),AnotherActivity.class);
intent.putExtra("keywords", keywords);
if(intent2!=null) {
final String Firstname=intent2.getString("firstName");
intent.putExtra("firstName", Firstname); }
intent.putExtra("lastName", intent2.getString("lastName"));
intent.putExtra("id", intent2.getString("id"));
}
startActivity(intent);
Parceable Class
public class LoginPart implements Parcelable{
private Token requestoken;
private OAuthService s;
private String authURL;
public LoginPart(Token Token, OAuthService S, String AuthURL) {
requestoken = Token;
s = S;
authURL = AuthURL;
}
public LoginPart( ) {
}
public Token getRequestoken() {
return requestoken;
}
public void setRequestoken(Token requestoken) {
this.requestoken = requestoken;
}
public OAuthService getS() {
return s;
}
public Parcelable getSParcelable() {
return (Parcelable) s;
}
public void setS(OAuthService s) {
this.s = s;
}
public String getAuthURL() {
return authURL;
}
public void setAuthURL(String authURL) {
this.authURL = authURL;
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeValue(requestoken);
dest.writeValue(s);
dest.writeValue(authURL);
}
}
Problem is related to Parcable class.When I use parceable class make crash.How can I solve that?
in your first activity:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
Bundle b = new Bundle();
b.putInt("id", 1);
b.putString("firstName", "this is my first name");
b.putString("lastName", "this is my last name");
intent.putExtras(b);
startActivity(intent);
in second activity:
Bundle b =getIntent().getExtras();
String name =b.getString("firstName");
String lastname =b.getString("lastName");
chane your LoginPart class like this...
public class LoginPart implements Parcelable {
private Token requestoken;
private OAuthService s;
private String authURL;
public LoginPart(Token Token, OAuthService S, String AuthURL) {
requestoken = Token;
s = S;
authURL = AuthURL;
}
public LoginPart( ) {
}
public LoginPart(Parcel parcel) {
requestoken = parcel.readValue(getClassLoader());
s = parcel.readValue(getClassLoader());
authURL = parcel.readValue(getClassLoader());
}
public Token getRequestoken() {
return requestoken;
}
public void setRequestoken(Token requestoken) {
this.requestoken = requestoken;
}
public OAuthService getS() {
return s;
}
public Parcelable getSParcelable() {
return (Parcelable) s;
}
public void setS(OAuthService s) {
this.s = s;
}
public String getAuthURL() {
return authURL;
}
public void setAuthURL(String authURL) {
this.authURL = authURL;
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeValue(requestoken);
dest.writeValue(s);
dest.writeValue(authURL);
}
public static final Parcelable.Creator<LoginPart> CREATOR = new Creator<SecondActivity.LoginPart>() {
#Override
public LoginPart[] newArray(int size) {
return new LoginPart[size];
}
#Override
public LoginPart createFromParcel(Parcel source) {
return new LoginPart(source);
}
};
}
for this to work, your Token class and OAuthService class should implement Parcelable
I have a NetworkList class which has a arraylist of type string. I am using parcelable interface in it.but i am getting only the first element of arraylist in my new activity.
how can i get all the elements?
here is NetworkList class
public class NetworkList implements Parcelable{
private ArrayList<String> name=new ArrayList<String>();
private ArrayList<String> id=new ArrayList<String>();
#SuppressWarnings("unchecked")
public NetworkList(Parcel in) {
// TODO Auto-generated constructor stub
name=in.readArrayList(null);
id=in.readArrayList(null);
}
public NetworkList() {
// TODO Auto-generated constructor stub
}
public void setName(String tempValue) {
// TODO Auto-generated method stub
this.name.add(tempValue);
}
public void setid(String tempValue) {
// TODO Auto-generated method stub
this.id.add(tempValue);
}
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeList(name);
dest.writeList(id);
}
public ArrayList<String> getname() {
return name;
}
public static final Creator<NetworkList> CREATOR = new Parcelable.Creator<NetworkList>() {
public NetworkList createFromParcel(Parcel in) {
return new NetworkList(in);
}
public NetworkList[] newArray(int size) {
return new NetworkList[size];
}
};
}
here is how where i pass it
Intent(AllNetworkActivity.this,WorkActivity.class);
intent.putExtra("name",network);
startActivity(intent);
}});
}
here is how i retrieve it
Bundle extras=getIntent().getExtras();
NetworkList network=(NetworkList)extras.getParcelable("name");
String name[]=new String[network.getname().size()];
for(int i=0;i<network.getname().size();i++){
name[i]=network.getname().get(i);
}
setListAdapter(new ArrayAdapter<String>(this,R.layout.work,name));
hope u are able to help me know
You should also look into Application class in Android. You can define global variables in there which can be accessed by all activities. However Bundle is the most popular and right method for sending data between activities.
Try using appropriate methods to serialize List<String>:
public NetworkList(Parcel in) {
in.readStringList(name);
in.readStringList(id);
}
public void writeToParcel(Parcel dest, int flags) {
// log the number of elements - check that this is actually what you expect it to be
// use only during development
Log.i("NetworkList"," number of elements = "+name.size())
dest.writeStringList(name);
dest.writeStringList(id);
}
first
Intent Jan = new Intent(Months.this,Holiday.class);
Jan.putExtra("ListCount", "Jan");
startActivity(Jan);
then
Bundle extras = getIntent().getExtras();
String data = extras.getString("ListCount");
if(data.equals("Jan")){
TextView txtMonth = (TextView)findViewById(R.id.txtMonth);
txtMonth.setText("January");
TextView txtDetail = (TextView)findViewById(R.id.txtDetail);
txtDetail.setText(R.string.JanHol);
}
check this post I wrote. Hope this will help you.