Aceofspadez44 Aceofspadez44 - 1 year ago 177
Android Question

DP5 7.0 - Does adding extras to a pending intent fail?

Adding the linked issue on tracker:

So I installed the DP5 Android 7.0 release onto my Nexus 5X today. I've been working on an app that schedules local notifications at specific times using Android's AlarmManager class. Up until this release, the code has been working great on devices running KitKat, Lollipop, and Marshmallow.

Below is how I'm scheduling the alarms:

Intent intent = new Intent(context, AlarmManagerUtil.class);
intent.putExtra(AlarmManagerUtil.REMINDER_EXTRA, Parcels.wrap(reminders));
intent.putExtra("time", when.getMillis());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (alarmManager != null) {
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, when.getMillis(), pendingIntent);
} else if (Build.VERSION.SDK_INT >= 19) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, when.getMillis(), pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, when.getMillis(), pendingIntent);

My AlarmManagerUtil @onReceive of the "SET_NOTIFICATION_INTENT" looks like this:

public void fireNotification(Context context, Intent intent) {
List<Reminder> reminderToFire = Parcels.unwrap(intent.getParcelableExtra(REMINDER_EXTRA));
long timeToFire = intent.getLongExtra("time", 0L); //.... }

What's strange is the "reminderToFire" is null here only on Android N devices but the timeToFire is correct.

I'm thinking its something to do with the Parceler Library? I'm compiling using Java 1.8 and targeting Android API 24.

I've definitely looked around the net for an answer to this, but my case is a bit unique since the code 100% works on all prior versions of Android (everything below N preview) I am following the below answers as much as I can:

How can I correctly pass unique extras to a pending intent?

Anybody else have this issue?

Answer Source

I have seen this sort of behavior reported before, with custom Parcelable objects and system services (e.g., NotificationManager). What seems to happen is that the system tries using the PendingIntent, and as part of that for some reason it tries to un-Parcel the Parcelable. This fails, because the system doesn't have your classes. I haven't heard of somebody running into this in a while, but it's entirely possible that there is a regression in Android N that re-introduced it.

You might rummage through LogCat to see if there are any messages — or, better yet, stack traces — from the system (not your app) that seem to pertain to your alarm event.

If you can create a reproducible test case, file an issue on the Android issue tracker. If you think of it, post a link to it here, as I'd like to take a peek at it.

In terms of workarounds, I can think of two:

  1. Don't put the Parcelable in there. Instead, put an ID that you can use to look up the information as needed, whether from an in-memory cache (if your process happens to still be around) or from whatever your persistent data store is.

  2. Switch from Parcelable to what I and others have termed "bundle-able", where you convert your object to and from a Bundle. Basically, stick solely to OS-defined classes, with no custom classes. Then, the system can safely de-Parcel the Bundle (for whatever reason it does so). This, of course, is much more painful than simply using an annotation processor to create the Parcelable implementation.