Número mágico defectuoso para Bundle en Android

Estoy pasando datos de una actividad a otra actividad con este código:

@Override public void execute(List<Report> reports, Questions question) { Intent replyIntent = new Intent(listener, ReplyActivity.class); replyIntent.putExtra("id", 0L); replyIntent.putExtra("questions", question); listener.openReportOk(question); listener.startActivity(replyIntent); } 

Listener es una referencia de actividad para callbacks.

Preguntas es esta clase:

 @Table(name = "Questions") public class Questions extends Entity implements Parcelable { public static final Creator<Questions> CREATOR = new Creator<Questions>() { public Questions createFromParcel(Parcel source) { return new Questions(source); } public Questions[] newArray(int size) { return new Questions[size]; } }; @TableField(name = "idReport", datatype = DATATYPE_INTEGER) private int idReport; @TableField(name = "nameReport", datatype = DATATYPE_STRING) private String nameReport; @TableField(name = "replyGroups", datatype = DATATYPE_STRING) private String replyGroups; @TableField(name = "questionGroups", datatype = DATATYPE_ENTITY) private List<QuestionsGroup> questionsGroup; private Boolean canCreateNew; public Questions(int idReport, String nameReport, String replyGroups, List<QuestionsGroup> questionsGroup) { this.idReport = idReport; this.nameReport = nameReport; this.replyGroups = replyGroups; this.questionsGroup = questionsGroup; this.canCreateNew = false; } public Questions() { questionsGroup = new ArrayList<QuestionsGroup>(); } private Questions(Parcel in) { this(); this.idReport = in.readInt(); this.nameReport = in.readString(); this.replyGroups = in.readString(); Bundle b = in.readBundle(QuestionsGroup.class.getClassLoader()); this.questionsGroup = b.getParcelableArrayList("questionGroups"); this.canCreateNew = (Boolean) in.readValue(Boolean.class.getClassLoader()); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(this.idReport); dest.writeString(this.nameReport); dest.writeString(this.replyGroups); Bundle b = new Bundle(); b.putParcelableArrayList("questionGroups", (ArrayList<QuestionsGroup>) this.questionsGroup); dest.writeBundle(b); dest.writeValue(this.canCreateNew); } } 

Y cuando recibo las parcelas en el método onCreate:

  private void getData(Intent data) { ID = data.getExtras().getLong("id"); questions = data.getExtras().getParcelable("questions"); } 

Estoy recibiendo este error:

 10-05 13:19:15.508 3499-3499/com.firext.android E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.firext.android, PID: 3499 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.firext.android/com.firext.android.activities.reply.ReplyActivity}: java.lang.IllegalStateException: Bad magic number for Bundle: 0x28 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2255) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2317) at android.app.ActivityThread.access$800(ActivityThread.java:143) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5070) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:631) Caused by: java.lang.IllegalStateException: Bad magic number for Bundle: 0x28 at android.os.BaseBundle.readFromParcelInner(BaseBundle.java:1342) at android.os.BaseBundle.<init>(BaseBundle.java:90) at android.os.Bundle.<init>(Bundle.java:66) at android.os.Parcel.readBundle(Parcel.java:1645) at com.firext.android.domain.QuestionsGroup.<init>(QuestionsGroup.java:53) at com.firext.android.domain.QuestionsGroup$1.createFromParcel(QuestionsGroup.java:25) at com.firext.android.domain.QuestionsGroup$1.createFromParcel(QuestionsGroup.java:23) at android.os.Parcel.readParcelable(Parcel.java:2160) at android.os.Parcel.readValue(Parcel.java:2066) at android.os.Parcel.readListInternal(Parcel.java:2422) at android.os.Parcel.readArrayList(Parcel.java:1756) at android.os.Parcel.readValue(Parcel.java:2087) at android.os.Parcel.readArrayMapInternal(Parcel.java:2393) at android.os.BaseBundle.unparcel(BaseBundle.java:221) at android.os.Bundle.getParcelableArrayList(Bundle.java:782) at com.firext.android.domain.Questions.<init>(Questions.java:58) at com.firext.android.domain.Questions.<init>(Questions.java:18) at com.firext.android.domain.Questions$1.createFromParcel(Questions.java:22) at com.firext.android.domain.Questions$1.createFromParcel(Questions.java:20) at android.os.Parcel.readParcelable(Parcel.java:2160) at android.os.Parcel.readValue(Parcel.java:2066) at android.os.Parcel.readArrayMapInternal(Parcel.java:2393) at android.os.BaseBundle.unparcel(BaseBundle.java:221) at android.os.Bundle.getParcelable(Bundle.java:738) at com.firext.android.activities.reply.ReplyActivity.getData(ReplyActivity.java:72) at com.firext.android.activities.reply.ReplyActivity.onCreate(ReplyActivity.java:38) at android.app.Activity.performCreate(Activity.java:5720) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1102) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2208)            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2317)            at android.app.ActivityThread.access$800(ActivityThread.java:143)            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258)            at android.os.Handler.dispatchMessage(Handler.java:102)            at android.os.Looper.loop(Looper.java:135)            at android.app.ActivityThread.main(ActivityThread.java:5070)            at java.lang.reflect.Method.invoke(Native Method)            at java.lang.reflect.Method.invoke(Method.java:372)            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:836)            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:631) 

¿Qué pasa?

Resumen

Parece que tienes un error en cómo almacenar y recuperar la información dividida de QuestionsGroup . La línea 53 es la línea a prestar la atención a.

Al escribir en la parcela, Android almacena un "número mágico" especial con cada campo, para asegurarse de que utiliza el orden correcto al extraer los campos del paquete (vea la explicación detallada para la definición del número).

Usted está recibiendo el error porque el número mágico no se encuentra en la posición esperada – esto es porque usted no está tomando los campos de la parcela en el orden correcto.


Explicación detallada del código fuente oficial

[La siguiente explicación se basa en la última implementación API21 de las clases Bundle y BaseBundle . Puedes encontrar el código completo aquí:

  • BaseBundle en android.googlesource.com

También puede utilizar el Administrador SDK de Android para instalar una copia local del código en su máquina de desarrollo, que me parece muy útil. ]

Asi que…

Cuando se escriben paquetes, Android lleva a cabo algunos pasos de seguridad para asegurarse de que los campos se alinean cuando intenta unparcel ellos. Para ello, Android anexa los campos con un "número mágico", definido como:

 static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L' 

Puede ver esto en el código de writeToParcelInner() (resumido a continuación)

 void writeToParcelInner(Parcel parcel, int flags) { if (mParcelledData != null) { if (mParcelledData == EMPTY_PARCEL) { parcel.writeInt(0); } else { int length = mParcelledData.dataSize(); parcel.writeInt(length); parcel.writeInt(BUNDLE_MAGIC); parcel.appendFrom(mParcelledData, 0, length); } } else { .......... extra code chopped out for illustration purposes } } 

Del mismo modo, al leer de la parcela, Android comprueba que BUNDLE_MAGIC número antes de devolver los valores de la parcela.

 private void readFromParcelInner(Parcel parcel, int length) { if (length == 0) { // Empty Bundle or end of data. mParcelledData = EMPTY_PARCEL; return; } int magic = parcel.readInt(); if (magic != BUNDLE_MAGIC) { //noinspection ThrowableInstanceNeverThrown throw new IllegalStateException("Bad magic number for Bundle: 0x" + Integer.toHexString(magic)); } .......... extra code chopped out for illustration purposes } 

En el código anterior de API21 BaseBundle , puede ver el error que se está lanzando en la línea 1342 según el rastreo logcat.


Solución alternativa y depuración adicional

El póster original indica que QuestionsGroup es correctamente parcelable.

Una manera de depurar más este problema sería alejarse de la (actualmente) nueva API21, que introdujo la clase BaseBundle ; Hasta API19 por ejemplo, que sólo utiliza la clase Bundle .

Si el código del usuario es realmente correcto, es más probable que trabaje en una API más madura.

Si el código sigue rompiendo, es probable que el código de QuestionsGroup . Sin embargo, además, el nuevo rastreo logcat señalará una parte diferente del código, que se puede examinar y puede proporcionar más información sobre el problema.

A menos que sea Bundle, línea 1730, del método readFromParcelInner() , lo que implicaría el mismo problema:

  int magic = parcel.readInt(); if (magic != BUNDLE_MAGIC) { //noinspection ThrowableInstanceNeverThrown throw new IllegalStateException("Bad magic number for Bundle: 0x" + Integer.toHexString(magic)); } 

Artículos Relacionados

Consulte las siguientes publicaciones para obtener información relacionada:

  • Android parcelable and Intent: redBundle: número mágico malo

Para ser honesto con usted, nunca conseguí tal del error. Pero utilizo una manera diferente de almacenar una list de parcelable ( QuestionsGroup ) dentro de mi parcelable ( Questions ):

  private Questions(Parcel in) { this(); this.idReport = in.readInt(); this.nameReport = in.readString(); this.replyGroups = in.readString(); //Bundle b = in.readBundle(QuestionsGroup.class.getClassLoader()); //this.questionsGroup = b.getParcelableArrayList("questionGroups"); this.questionsGroup = in.readTypedList(questionsGroup,QuestionsGroup.CREATOR); this.canCreateNew = (Boolean) in.readValue(Boolean.class.getClassLoader()); } 

Y:

 @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(this.idReport); dest.writeString(this.nameReport); dest.writeString(this.replyGroups); //Bundle b = new Bundle(); //b.putParcelableArrayList("questionGroups", (ArrayList<QuestionsGroup>) this.questionsGroup); //dest.writeBundle(b); dest.writeTypedList(questionsGroup); dest.writeValue(this.canCreateNew); } 

Utilizo el código de arriba en mis proyectos y su funcionamiento muy bien. Es posible que desee probarlo ya que es fácil y rápido.

En la clase de preguntas que está utilizando

  private List<QuestionsGroup> questionsGroup; 

Es Parcelable o no si no es parcelable o lo hace Parcelable o agrega transiet en declinaring QuestionGroup lista como: – abajo

 private transient List<QuestionsGroup> questionsGroup; 

En lugar de usar paquete, sólo analizar el id a la actividad objetivo y cargar la entidad de nuevo desde db o un almacén de memoria

  • Cómo obtener ClassLoader de variable de tipo (para parcelar una clase usando genéricos)
  • Problema en la implementación de Parcelable conteniendo otros Parcelable
  • Android JUnit no se compila si los objetos son parcelables
  • Parcelable, ¿qué es newArray para?
  • Cómo pasar una matriz de objetos de dirección a otra Acitvity
  • Ventajas de Parcelable sobre JSON
  • Enviar ArrayList <Object> de BroadCastReceiver a Actividad
  • Herencia parcelable: clase abstracta - ¿QUÉ CREADOR?
  • Cómo en Android pasar un objeto a un nuevo propósito
  • Clase abstracta como parcelable
  • Pase Arraylist en Actividad a Fragmento
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.