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.
- Códigos de tipo de desbloqueo y valor de compensación y su significado?
- Pasando un Cursor entre procesos (Cursor Parcelable)
- Pasar ArrayList <CustomObject> entre actividades
- Escritura de arreglos de Parcelables a un paquete en Android
- Android Class Parcelable con ArrayList
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?
- Implementar interfaz parcelable utilizando Gson
- No se puede pasar el objeto personalizado en un intento: El método Poner extra es ambiguo para el tipo Intención
- Paquete interior parcelable que se agrega a la parcela
- Pon el Objeto como intención para la siguiente actividad
- ¿Cómo enviar un objeto de una actividad a otra con Intent.putExtra y Parcel?
- Problema de desacoplamiento de parcelables
- No se puede guardar ArrayList de Uri en un archivo: NotSerializableException
- Android Parcelable en Kotlin
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
- Android ListView con múltiples selecciones y adaptadores personalizados
- Hacer fragmentos a pantalla completa mediante programación