Java.lang.RuntimeException: Parcel android.os.Parcel: Unmarshalling unknown code type

It seems that I get a strange error in my application (see GitHub ) that occurs when I pass objects into different actions that implement Parcelable .

I checked other questions and answers here about stack overflow, but I could not find a solution. I tried to answer here , for example - here it is for reference:

 -keepclassmembers class * implements android.os.Parcelable { static ** CREATOR; } 

I also made sure that the method calls writeToParcel . Most other stack overflow questions about this issue have no answers.

Also, the reason I'm asking a new question is because I think my problem is caused by the way I used the interfaces in my application (I'll talk about this later). Other stack overflow questions would not fit my specific scenario.

In the future, I provided links to the code through GitHub so you can learn more about the code, if necessary.


When I click on the button it starts a new action (passing in an object that implements Parcelable ), a crash occurs :

 Process: com.satsuware.flashcards, PID: 4664 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.satsuware.flashcards/com.satsumasoftware.flashcards.ui.FlashCardActivity}: java.lang.RuntimeException: Parcel android.os.Parcel@d2219e4 : Unmarshalling unknown type code 6815860 at offset 200 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) ... Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@d2219e4 : Unmarshalling unknown type code 6815860 at offset 200 at android.os.Parcel.readValue(Parcel.java:2319) at android.os.Parcel.readListInternal(Parcel.java:2633) at android.os.Parcel.readArrayList(Parcel.java:1914) at android.os.Parcel.readValue(Parcel.java:2264) at android.os.Parcel.readArrayMapInternal(Parcel.java:2592) at android.os.BaseBundle.unparcel(BaseBundle.java:221) at android.os.Bundle.getParcelable(Bundle.java:786) at android.content.Intent.getParcelableExtra(Intent.java:5377) at com.satsumasoftware.flashcards.ui.FlashCardActivity.onCreate(FlashCardActivity.java:71) at android.app.Activity.performCreate(Activity.java:6237) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) ... 

I call the above activity the same way (also see GitHub ):

 Intent intent = new Intent(TopicDetailActivity.this, FlashCardActivity.class); intent.putExtra(FlashCardActivity.EXTRA_TOPIC, mTopic); intent.putExtra(FlashCardActivity.EXTRA_NUM_CARDS, mSelectedNumCards); intent.putExtra(FlashCardActivity.EXTRA_CARD_LIST, mFilteredCards); startActivity(intent); 

The main part that should be considered is when I go through mTopic . This is the Topic interface I created.

However, the Topic interface extends Parcelable , so objects that implement Topic also include a constructor, a CREATOR field, and methods that should normally have a class that implements Parcelable .

You can view the corresponding classes through GitHub links, but I will talk about the corresponding parts of these classes below. Here is the Topic interface:

 public interface Topic extends Parcelable { int getId(); String getIdentifier(); String getName(); Course getCourse(); ArrayList<FlashCard> getFlashCards(Context context); class FlashCardsRetriever { public static ArrayList<FlashCard> filterStandardCards(ArrayList<FlashCard> flashCards, @StandardFlashCard.ContentType int contentType) { ArrayList<FlashCard> filteredCards = new ArrayList<>(); for (FlashCard flashCard : flashCards) { boolean isPaper2 = ((StandardFlashCard) flashCard).isPaper2(); boolean condition; switch (contentType) { case StandardFlashCard.PAPER_1: condition = !isPaper2; break; case StandardFlashCard.PAPER_2: condition = isPaper2; break; case StandardFlashCard.ALL: condition = true; break; default: throw new IllegalArgumentException("content type '" + contentType + "' is invalid"); } if (condition) filteredCards.add(flashCard); } return filteredCards; } ... } } 

The class (object) that implements Topic :

 public class CourseTopic implements Topic { ... public CourseTopic(int id, String identifier, String name, Course course) { ... } @Override public int getId() { return mId; } @Override public String getIdentifier() { return mIdentifier; } ... protected CourseTopic(Parcel in) { mId = in.readInt(); mIdentifier = in.readString(); mName = in.readString(); mCourse = in.readParcelable(Course.class.getClassLoader()); } public static final Parcelable.Creator<CourseTopic> CREATOR = new Parcelable.Creator<CourseTopic>() { @Override public CourseTopic createFromParcel(Parcel in) { return new CourseTopic(in); } @Override public CourseTopic[] newArray(int size) { return new CourseTopic[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mId); dest.writeString(mIdentifier); dest.writeString(mName); dest.writeParcelable(mCourse, flags); } } 

In one of the last lines of the code above, you can see that I am mCourse , which is the Course object that I created. Here he is:

 public class Course implements Parcelable { ... public Course(String subject, String examBoard, @FlashCard.CourseType String courseType, String revisionGuide) { ... } public String getSubjectIdentifier() { return mSubjectIdentifier; } public String getExamBoardIdentifier() { return mBoardIdentifier; } public ArrayList<Topic> getTopics(Context context) { ArrayList<Topic> topics = new ArrayList<>(); String filename = mSubjectIdentifier + "_" + mBoardIdentifier + "_topics.csv"; CsvParser parser = CsvUtils.getMyParser(); try { List<String[]> allRows = parser.parseAll(context.getAssets().open(filename)); for (String[] line : allRows) { int id = Integer.parseInt(line[0]); topics.add(new CourseTopic(id, line[1], line[2], this)); } } catch (IOException e) { e.printStackTrace(); } return topics; } ... protected Course(Parcel in) { mSubjectIdentifier = in.readString(); mBoardIdentifier = in.readString(); mCourseType = in.readString(); mRevisionGuide = in.readString(); } public static final Creator<Course> CREATOR = new Creator<Course>() { @Override public Course createFromParcel(Parcel in) { return new Course(in); } @Override public Course[] newArray(int size) { return new Course[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mSubjectIdentifier); dest.writeString(mBoardIdentifier); dest.writeString(mCourseType); dest.writeString(mRevisionGuide); } 

}

I suspect that something here may cause a problem, and for this reason my script is different from the others in matters.


Honestly, I'm not quite sure what might cause the error, so the explanations and recommendations in the answers will be very appreciated.


Edit

Following David Wasser's suggestions, I updated part of my code like this:

FlashCardActivity.java - onCreate(...) :

 Bundle extras = getIntent().getExtras(); extras.setClassLoader(Topic.class.getClassLoader()); mTopic = extras.getParcelable(EXTRA_TOPIC); 

Course.java - writeToParcel(...) :

 dest.writeString(mSubjectIdentifier); dest.writeString(mBoardIdentifier); dest.writeString(mCourseType); dest.writeInt(mRevisionGuide == null ? 0 : 1); if (mRevisionGuide != null) dest.writeString(mRevisionGuide); 

Course.java - Course(Parcel in) :

 mSubjectIdentifier = in.readString(); mBoardIdentifier = in.readString(); mCourseType = in.readString(); if (in.readInt() != 0) mRevisionGuide = in.readString(); 

I added log messages using Log.d(...) to see if any variables are equal to zero when passed to writeToParcel(...) and the David writeToParcel(...) method is used to properly handle this.

I still get the same error message.

+6
source share
1 answer

Your problem is LanguagesFlashCard . Here are your submit / delete methods:

 protected LanguagesFlashCard(Parcel in) { mId = in.readInt(); mEnglish = in.readString(); mAnswerPrefix = in.readString(); mAnswer = in.readString(); mTier = in.readInt(); mTopic = in.readParcelable(Topic.class.getClassLoader()); } 

As you can see, they do not match. The second element you write in Parcel is int , the second element you read from Parcel is String .

 @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mId); dest.writeInt(mTier); dest.writeString(mEnglish); dest.writeString(mAnswerPrefix); dest.writeString(mAnswer); dest.writeParcelable(mTopic, flags); } 
+17
source

All Articles