I am trying to pass Parcelable data from one intent to another and this is the error I am getting:
08-31 14:12:22.709: E/AndroidRuntime(9931): FATAL EXCEPTION: main
08-31 14:12:22.709: E/AndroidRuntime(9931): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.matejsoftware.cardscoretracker/com.matejsoftware.cardscoretracker.Igra}: android.os.BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called CREATOR on class com.matejsoftware.cardscoretracker.Novaigra$Player
The thing is: I do have Parcelable.Creator object. I'll post the whole Parcelable code below:
public class Player implements Parcelable{
String name;
int score;
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(score);
}
public Player(Parcel source){
score = source.readInt();
name = source.readString();
}
public Player(int score, String name){
this.score = score;
this.name = name;
}
}
public class MyCreator implements Parcelable.Creator<Player> {
@Override
public Player createFromParcel(Parcel source) {
return new Player(source);
}
@Override
public Player[] newArray(int size) {
return new Player[size];
}
}
Is there somethin wrong with the CREATOR? The app crashes as soon as I click the button to start the next activity.
This is how I "retrieve" Parcelable data in the second activity:
//global variable
ArrayList<Player> playersParceledData;
//This is in onCreate
playersData = getIntent();
playersParceledData = playersData.getParcelableArrayListExtra("parceledData");
Also, this is how I put class objects to ParcelableArrayListExtra:
Player newPlayer = new Player(0, text);
playersParceledData.add(newPlayer);
zacniIgro.putParcelableArrayListExtra("parceledData", playersParceledData);
You are have different sequence when reading from Parcel than the one you write in.
In writeToParcel()
you are first putting String but in the HeatFriendDetail(Parcel in)
, you first read integer. It is not the correct way because the order or read/write matters.
Following is the code which makes correct order when writing/reading the data to/from Parcel (also see this link):
public class FriendDetail implements Parcelable {
private String full_name;
private int privacy;
public HeatFriendDetail(Parcel in) {
this.full_name = in.readString();
this.privacy = in.readInt();
}
public HeatFriendDetail() {
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.full_name);
dest.writeInt(this.privacy);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public HeatFriendDetail createFromParcel(Parcel in) {
return new HeatFriendDetail(in);
}
public HeatFriendDetail[] newArray(int size) {
return new HeatFriendDetail[size];
}
};
// GETTER SETTER//
}
I received this error in release apk only, because the CREATOR was not public.
I changed this :
static final Parcelable.Creator<Station> CREATOR = new Parcelable.Creator<Station>() {
To this :
public static final Parcelable.Creator<Station> CREATOR = new Parcelable.Creator<Station>() {
Just ran into this.
I had a hunch, and I looked in my ProGuard mapping file.
Normally I declare CREATOR like this:
public static final Parcelable.Creator<ClassA> CREATOR =
new Parcelable.Creator<ClassA>() {
which shows up in the mapping file like this:
android.os.Parcelable$Creator CREATOR -> CREATOR
..except for one class, the class that was reported with the error. I declared it like this:
public static Creator<ClassB> CREATOR =
new Creator<ClassB>() {
Lo and behold:
android.os.Parcelable$Creator CREATOR -> a
So if you are getting this exception in your production release, check your mapping file. I think ProGuard is really sensitive to how CREATOR is declared when deciding not to obfuscate it.
I had this error message when the CREATOR class was not static
Try this way
// create List of player
ArrayList<HashMap<String, String>> players = new ArrayList<HashMap<String, String>>();
//create Player
HashMap<String, String> player = new HashMap<String, String>();
player.put("score", "20");//replace 20 with your score variable
player.put("name", "Biraj");//replace Biraj with your name variable
// Add to arraylist
players.add(player);
// pass to intent
Intent i;
i.putExtra("PLAYERS", players);
// read From intent
ArrayList<HashMap<String, String>> playerFromintent = (ArrayList<HashMap<String, String>>) getIntent().getSerializableExtra("PLAYERS");
// read from ArrayList
for (HashMap<String, String> hashMap : playerFromintent) {
System.out.println("Name : " + hashMap.get("name"));
System.out.println("Score : " + hashMap.get("score"));
}