You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Repository navigation
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
ClassCastException when using @Extra with Parcelable[] objects #1208
Caused by: java.lang.ClassCastException: android.os.Parcelable[] cannot be cast to com.myapp.media.RemoteMediaFile[]
at com.myapp.photos.RemotePhotoDetailActivity_.injectExtras_(RemotePhotoDetailActivity_.java:168)
at com.myapp.photos.RemotePhotoDetailActivity_.init_(RemotePhotoDetailActivity_.java:109)
at com.myapp.photos.RemotePhotoDetailActivity_.onCreate(RemotePhotoDetailActivity_.java:103)
at android.app.Activity.performCreate(Activity.java:5231)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
The generated code looks like this:
privatevoidinjectExtras_() {
Bundleextras_ = getIntent().getExtras();
if (extras_!= null) {
if (extras_.containsKey(REMOTE_FILES_EXTRA)) {
remoteFiles = ((RemoteMediaFile[]) extras_.getParcelableArray(REMOTE_FILES_EXTRA));
}
}
}
A fix would be to read the RemoteMediaFile[] object from the intent like this:
privatevoidinjectExtras_() {
Bundleextras_ = getIntent().getExtras();
if (extras_!= null) {
if (extras_.containsKey(REMOTE_FILES_EXTRA)) {
Parcelable[] a = extras_.getParcelableArrayExtra(REMOTE_FILES_EXTRA);
remoteFiles = Arrays.copyOf(a, a.length, RemoteMediaFile[].class);
}
}
}
changed the title [-]@Extra for Parcelable[] objects generates ClassCastException[/-][+]ClassCastException when using @Extra with Parcelable[] objects[/+]on Nov 5, 2014
BTW we have a test for all types of extras. This defect was not discovered there because in the load test, we set the field directly with Reflection, so the type is still MyParcelableBean[] and the cast is successful. I wonder we should create another test, which uses the generated method to save the field, and the generated method to get to the field. But that would not be a unit test.
i just tried your test fixture. It seems Robolectric getParcelableArray returns the type you put it in the first place. But in real Android getParcelableArray return Parcelable[].
Also please note we use Android 4.1 in Robolectric, but i tested with Android 4.4 on a real device. Maybe the behavior of getParcelableArray changed between the two versions?
This defect was not discovered there because in the load test, we set the field directly with Reflection
I just reviewed the test and this is not true, i looked at it too quickly. We indeed save into a Bundle and load from that, so another test is not necessary. The test passed though, because the suspected bug in Robolectric you discovered. I opened robolectric/robolectric#1440 for that.
@GaidamakUA i already proposed #1294 to fix this issue. You can build AA from that branch and use it. Or if you want to stick to the stable version, declare Parcelable[] as your @Extra object's type, then copy it to a specific array type manually, or just retrieve elements from it and cast them.
Note that Parcelable ClassCastException can occur as a mistyped exception when the
member variables are null and are written to the out Parcel..
One practice you could adopt in writeToParcel is to write an int flag of 0 or 1 before
deciding to write a variable (e.g. 0 for null).
Then in the read parcel method, you would read the flag to know whether there is a
variable to read next.
Activity
[-]@Extra for Parcelable[] objects generates ClassCastException[/-][+]ClassCastException when using @Extra with Parcelable[] objects[/+]WonderCsabo commentedon Nov 5, 2014
Can you post the code which adds the extra to the Intent?
ened commentedon Nov 5, 2014
WonderCsabo commentedon Nov 5, 2014
Thanks for the detailed report! You are right, this is indeed an issue. We have to add a special case for this in
BundleHelper. Wanna contribute?WonderCsabo commentedon Nov 5, 2014
BTW we have a test for all types of extras. This defect was not discovered there because in the load test, we set the field directly with Reflection, so the type is still
MyParcelableBean[]and the cast is successful. I wonder we should create another test, which uses the generated method to save the field, and the generated method to get to the field. But that would not be a unit test.ened commentedon Nov 9, 2014
I think this will be a simple test extension of
ExtraInjectedActivityandInjectExtraTest.WonderCsabo commentedon Nov 9, 2014
Yes indeed, that is the right place for this.
ened commentedon Nov 9, 2014
There's a class
CustomData. I'm thinking to re-use that one (add aimplements Parcelable). Guess that's what it was made for.WonderCsabo commentedon Nov 9, 2014
Please another class instead. If the class would implement both
SerializableandParcelabletheIntent.putExtramethod call would be ambiguous.ened commentedon Nov 9, 2014
CustomParcelableDatait is. :-)ened commentedon Nov 14, 2014
@WonderCsabo I've started to add the tests, could you have a look at https://github.com/ened/androidannotations/compare/parcelable-array ? The weird thing is: the test passes. :-)
I wonder if the please really is correct?
WonderCsabo commentedon Nov 14, 2014
i just tried your test fixture. It seems Robolectric
getParcelableArrayreturns the type you put it in the first place. But in real AndroidgetParcelableArrayreturnParcelable[].Also please note we use Android 4.1 in Robolectric, but i tested with Android 4.4 on a real device. Maybe the behavior of
getParcelableArraychanged between the two versions?ened commentedon Nov 14, 2014
Alright I'll test this out in the 4.1&4.4 emulator.
WonderCsabo commentedon Nov 14, 2014
Thanks.
WonderCsabo commentedon Nov 21, 2014
@ened did you have time for trying that out?
ened commentedon Nov 21, 2014
This weekend. :-)
ened commentedon Dec 7, 2014
@WonderCsabo I've been trying to get my head around the code & think it will take a bit longer.
WonderCsabo commentedon Dec 22, 2014
@ened any news on this?
WonderCsabo commentedon Dec 27, 2014
I wrote this in November:
I just reviewed the test and this is not true, i looked at it too quickly. We indeed save into a
Bundleand load from that, so another test is not necessary. The test passed though, because the suspected bug in Robolectric you discovered. I opened robolectric/robolectric#1440 for that.ened commentedon Dec 28, 2014
Thanks for taking the time to look into this.
I've been trying to dig into this for quite a bit - anyone who is faster is welcome to help out.
GaidamakUA commentedon Jan 5, 2015
I've faced this issue. I'm sorry for noobie question. Should I use some workaround, or I can get fix somehow?
WonderCsabo commentedon Jan 5, 2015
@GaidamakUA i already proposed #1294 to fix this issue. You can build AA from that branch and use it. Or if you want to stick to the stable version, declare
Parcelable[]as your@Extraobject's type, then copy it to a specific array type manually, or just retrieve elements from it and cast them.GaidamakUA commentedon Jan 5, 2015
@WonderCsabo Thank you.
nking commentedon Feb 21, 2018
Note that Parcelable ClassCastException can occur as a mistyped exception when the
member variables are null and are written to the out Parcel..
One practice you could adopt in writeToParcel is to write an int flag of 0 or 1 before
deciding to write a variable (e.g. 0 for null).
Then in the read parcel method, you would read the flag to know whether there is a
variable to read next.