J'essaie de transmettre des données parcellaires d'une intention à une autre et voici l'erreur que j'obtiens:
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
La chose est: j'ai un objet Parcelable.Creator. Je posterai l'intégralité du code Parcelable ci-dessous:
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];
}
}
Y a-t-il quelque chose de mal avec le CRÉATEUR? L'application se bloque dès que je clique sur le bouton pour démarrer la prochaine activité.
Voici comment je "récupère" les données parcellaires dans la deuxième activité:
//global variable
ArrayList<Player> playersParceledData;
//This is in onCreate
playersData = getIntent();
playersParceledData = playersData.getParcelableArrayListExtra("parceledData");
Aussi, voici comment je mets des objets de classe à ParcelableArrayListExtra:
Player newPlayer = new Player(0, text);
playersParceledData.add(newPlayer);
zacniIgro.putParcelableArrayListExtra("parceledData", playersParceledData);
Vous avez une séquence différente lors de la lecture de Parcel que celle que vous écrivez.
Dans writeToParcel()
vous mettez d'abord String mais dans HeatFriendDetail(Parcel in)
, vous lisez d'abord entier. Ce n'est pas la bonne façon car l'ordre ou la lecture/écriture est important.
Voici le code qui rend l'ordre correct lors de l'écriture/lecture des données vers/depuis le colis (voir également ce lien ):
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//
}
J'ai reçu cette erreur uniquement dans la version apk, car le CREATEUR n'était pas public.
J'ai changé ça:
static final Parcelable.Creator<Station> CREATOR = new Parcelable.Creator<Station>() {
Pour ça :
public static final Parcelable.Creator<Station> CREATOR = new Parcelable.Creator<Station>() {
Je suis juste tombé sur ça.
J'avais une intuition et j'ai regardé dans mon fichier de mappage ProGuard.
Normalement, je déclare CREATOR comme ceci:
public static final Parcelable.Creator<ClassA> CREATOR =
new Parcelable.Creator<ClassA>() {
qui apparaît dans le fichier de mappage comme ceci:
Android.os.Parcelable$Creator CREATOR -> CREATOR
..except pour une classe, la classe signalée avec l'erreur. Je l'ai déclaré comme ceci:
public static Creator<ClassB> CREATOR =
new Creator<ClassB>() {
Et voilà:
Android.os.Parcelable$Creator CREATOR -> a
Donc, si vous obtenez cette exception dans votre version de production, vérifiez votre fichier de mappage. Je pense que ProGuard est vraiment sensible à la façon dont CREATOR est déclaré lorsqu'il décide de ne pas le masquer.
J'ai eu ce message d'erreur lorsque la classe CREATOR n'était pas statique
Si vous utilisez des règles proguard ajoutez cette ligne à votre proguard-rules.pro
-keepnames class * implements Android.os.Parcelable {
public static final ** CREATOR;
}