Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bad magic number for Bundle in Android

I'm passing data from one activity to other activity with this code:

 @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 its a Activity reference for callbacks.

Questions is this class:

@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);
    }
}

And when i receive the parcels in onCreate method:

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

Im getting this 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)

Whats wrong?

like image 404
colymore Avatar asked Oct 05 '14 11:10

colymore


People also ask

What is bad magic number error in Python?

importerror: bad magic number error occurs mainly in random module python with Ubuntu operating system because of byte prefix in .pyc file. Actually, what happens with unix-oriented operating systems, The operating system assigns the first few BYTES of the file as an identifier or marker with the file. This is nothing but the magic numbers.

How to use bundle in Android with intent?

The bundle is always used with Intent in Android. Now to use Bundle writes the below code in the MainActivity. // starting the activity by passing the intent to it. Now create another empty activity named SecondActivity. Now to retrieve the data stored in the Bundle, write the following code in SecondActivity.

How to retrieve data from a bundle in an activity?

// starting the activity by passing the intent to it. Now create another empty activity named SecondActivity. Now to retrieve the data stored in the Bundle, write the following code in SecondActivity. Alternatively, if one does not want to use the default value too, one can do this but remember it gives an exception.

How to pass an empty or non-empty bundle from one activity?

The complete code for the activity_main.xml file is given below. Here one can see that the first button is used to pass the non-empty bundle, while the second button is used to pass the empty bundle. Now create another empty activity names SecondActivity.


1 Answers

Summary

It looks like you have an error in how you store & retrieve the parcelled information of QuestionsGroup. Line 53 is the line to pay attention to.

When writing to the parcel, Android stores a special "magic number" with each field, to ensure that you use the correct order when pulling fields out of the parcel (see detailed explanation for the definition of the number).

You are getting the error because the magic number is not found in the expected position - this is because you are not taking the fields out of the parcel in the correct order.


Detailed Explanation from Official Source Code

[ Below explanation is based on the "latest" (at time of writing) API21 implementation of the Bundle and BaseBundle classes. You can find the full code here:

  • BaseBundle on android.googlesource.com

You can also use the Android SDK Manager to install a local copy of the code onto your development machine, which I find very useful. ]

So...

When parcels are written, Android takes some security steps to ensure that the fields line up when you try to unparcel them. To do this, Android appends the fields with a "magic number", defined as:

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

You can see this in the code for writeToParcelInner() (summarised below)

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

    }
}

Similarly, when reading from the parcel, Android checks for that BUNDLE_MAGIC number before returning the values from the parcel.

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

}

In the above code for API21 BaseBundle, you can see your error being thrown on line 1342 as per the logcat trace.


Workaround & Further Debugging

Original poster states that QuestionsGroup is correctly parcelable.

One way to further debug this issue would be to move away from the (currently) new API21, which introduced the BaseBundle class; down to API19 for example which just uses the Bundle class.

If the user's code is actually correct, then it is more likely to work on a more mature API.

If the code still breaks, it is likely the QuestionsGroup code. However, in addition the new logcat trace will point to a different part of the code, which can be looked at and may provide more insight into the problem.

Unless it is to Bundle, line 1730, from method readFromParcelInner(), which would imply the same problem:

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

Related Posts

See the following posts for related information:

  • Android parcelable and Intent: redBundle: bad magic number
like image 150
Richard Le Mesurier Avatar answered Sep 30 '22 15:09

Richard Le Mesurier