From 16a853157b68bd63d0ed67334185b4f04d731149 Mon Sep 17 00:00:00 2001 From: Phillip Hsu Date: Mon, 5 Sep 2016 00:22:58 -0700 Subject: [PATCH] Fix occurrences of crashing by snoozing alarm from notification by parceling and unparceling Alarm in UpcomingAlarmReceiver instead of retrieving from database with long id --- .../clock2/UpcomingAlarmReceiver.java | 97 ++++++++----------- .../clock2/util/AlarmController.java | 4 +- .../philliphsu/clock2/util/AlarmUtils.java | 4 +- 3 files changed, 46 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/com/philliphsu/clock2/UpcomingAlarmReceiver.java b/app/src/main/java/com/philliphsu/clock2/UpcomingAlarmReceiver.java index 39c2a20..3ec19b1 100644 --- a/app/src/main/java/com/philliphsu/clock2/UpcomingAlarmReceiver.java +++ b/app/src/main/java/com/philliphsu/clock2/UpcomingAlarmReceiver.java @@ -6,16 +6,12 @@ import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.os.AsyncTask; import android.support.v4.app.NotificationCompat; -import com.philliphsu.clock2.model.AlarmCursor; -import com.philliphsu.clock2.model.AlarmsTableManager; import com.philliphsu.clock2.util.AlarmController; import static android.app.PendingIntent.FLAG_ONE_SHOT; import static com.philliphsu.clock2.util.DateFormatUtils.formatTime; -import static com.philliphsu.clock2.util.Preconditions.checkNotNull; // TODO: Consider registering this locally instead of in the manifest. public class UpcomingAlarmReceiver extends BroadcastReceiver { @@ -25,69 +21,60 @@ public class UpcomingAlarmReceiver extends BroadcastReceiver { public static final String ACTION_CANCEL_NOTIFICATION = "com.philliphsu.clock2.action.CANCEL_NOTIFICATION"; public static final String ACTION_SHOW_SNOOZING = "com.philliphsu.clock2.action.SHOW_SNOOZING"; - public static final String EXTRA_ALARM_ID = "com.philliphsu.clock2.extra.ALARM_ID"; + public static final String EXTRA_ALARM = "com.philliphsu.clock2.extra.ALARM"; @Override public void onReceive(final Context context, final Intent intent) { - final long id = intent.getLongExtra(EXTRA_ALARM_ID, -1); - if (id < 0) { - throw new IllegalStateException("No alarm id received"); + final Alarm alarm = intent.getParcelableExtra(EXTRA_ALARM); + if (alarm == null) { + throw new IllegalStateException("No alarm received"); } + final long id = alarm.getId(); final NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + if (ACTION_CANCEL_NOTIFICATION.equals(intent.getAction())) { nm.cancel(TAG, (int) id); } else { - new AsyncTask() { - @Override - protected Alarm doInBackground(Void... params) { - AlarmCursor cursor = new AlarmsTableManager(context).queryItem(id); - return checkNotNull(cursor.getItem()); - } - - @Override - protected void onPostExecute(Alarm alarm) { - if (ACTION_DISMISS_NOW.equals(intent.getAction())) { - new AlarmController(context, null).cancelAlarm(alarm, false); - } else { - // Prepare notification - // http://stackoverflow.com/a/15803726/5055032 - // Notifications aren't updated on the UI thread, so we could have - // done this in the background. However, no lengthy operations are - // done here, so doing so is a premature optimization. - String title; - String text; - if (ACTION_SHOW_SNOOZING.equals(intent.getAction())) { - if (!alarm.isSnoozed()) - throw new IllegalStateException("Can't show snoozing notif. if alarm not snoozed!"); - title = alarm.label().isEmpty() ? context.getString(R.string.alarm) : alarm.label(); - text = context.getString(R.string.title_snoozing_until, - formatTime(context, alarm.snoozingUntil())); - } else { - // No intent action required for default behavior - title = context.getString(R.string.upcoming_alarm); - text = formatTime(context, alarm.ringsAt()); - if (!alarm.label().isEmpty()) { - text = alarm.label() + ", " + text; - } - } - - Intent in = new Intent(context, UpcomingAlarmReceiver.class) - .putExtra(EXTRA_ALARM_ID, id) // TOneverDO: cast to int - .setAction(ACTION_DISMISS_NOW); - PendingIntent pi = PendingIntent.getBroadcast(context, (int) id, in, FLAG_ONE_SHOT); - Notification note = new NotificationCompat.Builder(context) - .setSmallIcon(R.mipmap.ic_launcher) // TODO: alarm icon - .setContentTitle(title) - .setContentText(text) - .setOngoing(true) - .addAction(R.mipmap.ic_launcher, context.getString(R.string.dismiss_now), pi) - .build(); - nm.notify(TAG, (int) id, note); + if (ACTION_DISMISS_NOW.equals(intent.getAction())) { + new AlarmController(context, null).cancelAlarm(alarm, false); + } else { + // Prepare notification + // http://stackoverflow.com/a/15803726/5055032 + // Notifications aren't updated on the UI thread, so we could have + // done this in the background. However, no lengthy operations are + // done here, so doing so is a premature optimization. + String title; + String text; + if (ACTION_SHOW_SNOOZING.equals(intent.getAction())) { + if (!alarm.isSnoozed()) + throw new IllegalStateException("Can't show snoozing notif. if alarm not snoozed!"); + title = alarm.label().isEmpty() ? context.getString(R.string.alarm) : alarm.label(); + text = context.getString(R.string.title_snoozing_until, + formatTime(context, alarm.snoozingUntil())); + } else { + // No intent action required for default behavior + title = context.getString(R.string.upcoming_alarm); + text = formatTime(context, alarm.ringsAt()); + if (!alarm.label().isEmpty()) { + text = alarm.label() + ", " + text; } } - }.execute(); + + Intent in = new Intent(context, UpcomingAlarmReceiver.class) + .putExtra(EXTRA_ALARM, alarm) + .setAction(ACTION_DISMISS_NOW); + PendingIntent pi = PendingIntent.getBroadcast(context, (int) id, in, FLAG_ONE_SHOT); + Notification note = new NotificationCompat.Builder(context) + .setSmallIcon(R.mipmap.ic_launcher) // TODO: alarm icon + .setContentTitle(title) + .setContentText(text) + .setOngoing(true) + .addAction(R.mipmap.ic_launcher, context.getString(R.string.dismiss_now), pi) + .build(); + nm.notify(TAG, (int) id, note); + } } } } diff --git a/app/src/main/java/com/philliphsu/clock2/util/AlarmController.java b/app/src/main/java/com/philliphsu/clock2/util/AlarmController.java index 74f15e4..87a9379 100644 --- a/app/src/main/java/com/philliphsu/clock2/util/AlarmController.java +++ b/app/src/main/java/com/philliphsu/clock2/util/AlarmController.java @@ -168,7 +168,7 @@ public final class AlarmController { public void removeUpcomingAlarmNotification(Alarm a) { Intent intent = new Intent(mAppContext, UpcomingAlarmReceiver.class) .setAction(UpcomingAlarmReceiver.ACTION_CANCEL_NOTIFICATION) - .putExtra(UpcomingAlarmReceiver.EXTRA_ALARM_ID, a.id()); + .putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, a); mAppContext.sendBroadcast(intent); } @@ -200,7 +200,7 @@ public final class AlarmController { private PendingIntent notifyUpcomingAlarmIntent(Alarm alarm, boolean retrievePrevious) { Intent intent = new Intent(mAppContext, UpcomingAlarmReceiver.class) - .putExtra(UpcomingAlarmReceiver.EXTRA_ALARM_ID, alarm.id()); + .putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, alarm); if (alarm.isSnoozed()) { // TODO: Will this affect retrieving a previous instance? Say if the previous instance // didn't have this action set initially, but at a later time we made a new instance diff --git a/app/src/main/java/com/philliphsu/clock2/util/AlarmUtils.java b/app/src/main/java/com/philliphsu/clock2/util/AlarmUtils.java index f31a25d..d950f3a 100644 --- a/app/src/main/java/com/philliphsu/clock2/util/AlarmUtils.java +++ b/app/src/main/java/com/philliphsu/clock2/util/AlarmUtils.java @@ -152,7 +152,7 @@ public final class AlarmUtils { public static void removeUpcomingAlarmNotification(Context c, Alarm a) { Intent intent = new Intent(c, UpcomingAlarmReceiver.class) .setAction(UpcomingAlarmReceiver.ACTION_CANCEL_NOTIFICATION) - .putExtra(UpcomingAlarmReceiver.EXTRA_ALARM_ID, a.id()); + .putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, a); c.sendBroadcast(intent); } @@ -196,7 +196,7 @@ public final class AlarmUtils { private static PendingIntent notifyUpcomingAlarmIntent(Context context, Alarm alarm, boolean retrievePrevious) { Intent intent = new Intent(context, UpcomingAlarmReceiver.class) - .putExtra(UpcomingAlarmReceiver.EXTRA_ALARM_ID, alarm.id()); + .putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, alarm); if (alarm.isSnoozed()) { // TODO: Will this affect retrieving a previous instance? Say if the previous instance // didn't have this action set initially, but at a later time we made a new instance