私はあるインテントから別のインテントにパーセル可能なデータを渡そうとしていますが、これは私が得ているエラーです:
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
問題は、Parcelable.Creatorオブジェクトがあることです。パーセル可能なコード全体を以下に投稿します。
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];
}
}
CREATORに何か問題がありますか?ボタンをクリックして次のアクティビティを開始するとすぐにアプリがクラッシュします。
これは、2番目のアクティビティでパーセル可能なデータを「取得」する方法です。
//global variable
ArrayList<Player> playersParceledData;
//This is in onCreate
playersData = getIntent();
playersParceledData = playersData.getParcelableArrayListExtra("parceledData");
また、これはクラスオブジェクトをParcelableArrayListExtraに配置する方法です。
Player newPlayer = new Player(0, text);
playersParceledData.add(newPlayer);
zacniIgro.putParcelableArrayListExtra("parceledData", playersParceledData);
パーセルから読み取るときの順序は、書き込む順序とは異なります。
writeToParcel()
では最初にStringを入力しますが、HeatFriendDetail(Parcel in)
では最初に整数を読み取ります。順序または読み取り/書き込みが重要であるため、正しい方法ではありません。
以下は、パーセルとの間でデータを読み書きするときに正しい順序を作成するコードです( このリンク も参照)。
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//
}
CREATORがパブリックではなかったため、リリースapkでのみこのエラーを受け取りました。
私はこれを変更しました:
static final Parcelable.Creator<Station> CREATOR = new Parcelable.Creator<Station>() {
これに:
public static final Parcelable.Creator<Station> CREATOR = new Parcelable.Creator<Station>() {
これに出くわしました。
気がついたので、ProGuardマッピングファイルを調べました。
通常、次のようにCREATORを宣言します。
public static final Parcelable.Creator<ClassA> CREATOR =
new Parcelable.Creator<ClassA>() {
次のようなマッピングファイルに表示されます。
Android.os.Parcelable$Creator CREATOR -> CREATOR
..1つのクラス、エラーが報告されたクラスを除きます。私はこのように宣言しました:
public static Creator<ClassB> CREATOR =
new Creator<ClassB>() {
Loと見よ:
Android.os.Parcelable$Creator CREATOR -> a
したがって、本番リリースでこの例外が発生する場合は、マッピングファイルを確認してください。 ProGuardは、CREATORを難読化しないことを決定する際の宣言方法に非常に敏感だと思います。
CREATORクラスが静的ではないときにこのエラーメッセージが表示されました
Proguardルールを使用している場合、この行をproguard-rules.proに追加します
-keepnames class * implements Android.os.Parcelable {
public static final ** CREATOR;
}