Be Careful Where You Use Custom Parcelables
Custom Parcelable
classes — ones unique to your app, not a part
of the Android framework — have had intermittent problems over
the years when used as Intent
extras. Basically, if a core OS process
needs to modify the Intent
extras, that process winds up trying
to recreate your Parcelable
objects as part of setting up the
extras Bundle
for modification. That process does not have your
class and so it gets a runtime exception.
One area where this can occur is with AlarmManager
. Code that used
custom Parcelable
objects with AlarmManager
that might have worked
on older versions of Android will not work on Android N.
Completely in-process uses of custom Parcelable
objects, such as
extras on LocalBroadcastManager
Intents
, is safe. Using custom
Parcelables
in the saved instance state Bundle
should be safe.
UPDATE 25 July 2016: Apparently, I spoke too soon on the saved
instance state Bundle
. Usually, that is OK. For whatever reason,
Maps V2 screws it up.
Many thanks to Olivier Lefevre for pointing this out!
The further afield from that you get — including any place where
you might distribute a PendingIntent
— be careful and be sure
to test thoroughly.
One workaround, such as it is, is to load the data from persistent
storage when needed, perhaps using a process-level cache if your process
still happens to be around. So, for example, suppose you used
PendingIntent.getBroadcast()
with AlarmManager
. Rather than put
a custom Parcelable
in the Intent
extra, just include enough
key data to know what you need. Then, as part of processing the alarm
event, go grab that data from cache or storage.
Another approach is to switch from Parcelable
to “bundleable”:
convert your object to and from a Bundle
, sticking to framework-defined
classes for all the contents of the Bundle
. Since all the classes
are available to all relevant processes, you should not run into the
sort of problem that you get from custom Parcelable
classes.
I assume that the problem with Parcelable
will also affect
Serializable
, though I am not certain of that.
UPDATE 23 July 2016: Matthias Urhahn
pointed out
another workaround: convert the Parcelable
into a byte[]
yourself,
storing that in the Bundle
. Then, the OS process will just treat
it as some random byte[]
. This Stack Overflow answer
shows the technique.