Fix occurrences of crashing by snoozing alarm from notification by parceling and unparceling Alarm in UpcomingAlarmReceiver instead of retrieving from database with long id
This commit is contained in:
parent
d44caf5255
commit
16a853157b
@ -6,16 +6,12 @@ import android.app.PendingIntent;
|
|||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
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 com.philliphsu.clock2.util.AlarmController;
|
||||||
|
|
||||||
import static android.app.PendingIntent.FLAG_ONE_SHOT;
|
import static android.app.PendingIntent.FLAG_ONE_SHOT;
|
||||||
import static com.philliphsu.clock2.util.DateFormatUtils.formatTime;
|
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.
|
// TODO: Consider registering this locally instead of in the manifest.
|
||||||
public class UpcomingAlarmReceiver extends BroadcastReceiver {
|
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_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 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
|
@Override
|
||||||
public void onReceive(final Context context, final Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
final long id = intent.getLongExtra(EXTRA_ALARM_ID, -1);
|
final Alarm alarm = intent.getParcelableExtra(EXTRA_ALARM);
|
||||||
if (id < 0) {
|
if (alarm == null) {
|
||||||
throw new IllegalStateException("No alarm id received");
|
throw new IllegalStateException("No alarm received");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final long id = alarm.getId();
|
||||||
final NotificationManager nm = (NotificationManager)
|
final NotificationManager nm = (NotificationManager)
|
||||||
context.getSystemService(Context.NOTIFICATION_SERVICE);
|
context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
if (ACTION_CANCEL_NOTIFICATION.equals(intent.getAction())) {
|
if (ACTION_CANCEL_NOTIFICATION.equals(intent.getAction())) {
|
||||||
nm.cancel(TAG, (int) id);
|
nm.cancel(TAG, (int) id);
|
||||||
} else {
|
} else {
|
||||||
new AsyncTask<Void, Void, Alarm>() {
|
if (ACTION_DISMISS_NOW.equals(intent.getAction())) {
|
||||||
@Override
|
new AlarmController(context, null).cancelAlarm(alarm, false);
|
||||||
protected Alarm doInBackground(Void... params) {
|
} else {
|
||||||
AlarmCursor cursor = new AlarmsTableManager(context).queryItem(id);
|
// Prepare notification
|
||||||
return checkNotNull(cursor.getItem());
|
// 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
|
||||||
@Override
|
// done here, so doing so is a premature optimization.
|
||||||
protected void onPostExecute(Alarm alarm) {
|
String title;
|
||||||
if (ACTION_DISMISS_NOW.equals(intent.getAction())) {
|
String text;
|
||||||
new AlarmController(context, null).cancelAlarm(alarm, false);
|
if (ACTION_SHOW_SNOOZING.equals(intent.getAction())) {
|
||||||
} else {
|
if (!alarm.isSnoozed())
|
||||||
// Prepare notification
|
throw new IllegalStateException("Can't show snoozing notif. if alarm not snoozed!");
|
||||||
// http://stackoverflow.com/a/15803726/5055032
|
title = alarm.label().isEmpty() ? context.getString(R.string.alarm) : alarm.label();
|
||||||
// Notifications aren't updated on the UI thread, so we could have
|
text = context.getString(R.string.title_snoozing_until,
|
||||||
// done this in the background. However, no lengthy operations are
|
formatTime(context, alarm.snoozingUntil()));
|
||||||
// done here, so doing so is a premature optimization.
|
} else {
|
||||||
String title;
|
// No intent action required for default behavior
|
||||||
String text;
|
title = context.getString(R.string.upcoming_alarm);
|
||||||
if (ACTION_SHOW_SNOOZING.equals(intent.getAction())) {
|
text = formatTime(context, alarm.ringsAt());
|
||||||
if (!alarm.isSnoozed())
|
if (!alarm.label().isEmpty()) {
|
||||||
throw new IllegalStateException("Can't show snoozing notif. if alarm not snoozed!");
|
text = alarm.label() + ", " + text;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -168,7 +168,7 @@ public final class AlarmController {
|
|||||||
public void removeUpcomingAlarmNotification(Alarm a) {
|
public void removeUpcomingAlarmNotification(Alarm a) {
|
||||||
Intent intent = new Intent(mAppContext, UpcomingAlarmReceiver.class)
|
Intent intent = new Intent(mAppContext, UpcomingAlarmReceiver.class)
|
||||||
.setAction(UpcomingAlarmReceiver.ACTION_CANCEL_NOTIFICATION)
|
.setAction(UpcomingAlarmReceiver.ACTION_CANCEL_NOTIFICATION)
|
||||||
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM_ID, a.id());
|
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, a);
|
||||||
mAppContext.sendBroadcast(intent);
|
mAppContext.sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ public final class AlarmController {
|
|||||||
|
|
||||||
private PendingIntent notifyUpcomingAlarmIntent(Alarm alarm, boolean retrievePrevious) {
|
private PendingIntent notifyUpcomingAlarmIntent(Alarm alarm, boolean retrievePrevious) {
|
||||||
Intent intent = new Intent(mAppContext, UpcomingAlarmReceiver.class)
|
Intent intent = new Intent(mAppContext, UpcomingAlarmReceiver.class)
|
||||||
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM_ID, alarm.id());
|
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, alarm);
|
||||||
if (alarm.isSnoozed()) {
|
if (alarm.isSnoozed()) {
|
||||||
// TODO: Will this affect retrieving a previous instance? Say if the previous instance
|
// 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
|
// didn't have this action set initially, but at a later time we made a new instance
|
||||||
|
|||||||
@ -152,7 +152,7 @@ public final class AlarmUtils {
|
|||||||
public static void removeUpcomingAlarmNotification(Context c, Alarm a) {
|
public static void removeUpcomingAlarmNotification(Context c, Alarm a) {
|
||||||
Intent intent = new Intent(c, UpcomingAlarmReceiver.class)
|
Intent intent = new Intent(c, UpcomingAlarmReceiver.class)
|
||||||
.setAction(UpcomingAlarmReceiver.ACTION_CANCEL_NOTIFICATION)
|
.setAction(UpcomingAlarmReceiver.ACTION_CANCEL_NOTIFICATION)
|
||||||
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM_ID, a.id());
|
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, a);
|
||||||
c.sendBroadcast(intent);
|
c.sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ public final class AlarmUtils {
|
|||||||
|
|
||||||
private static PendingIntent notifyUpcomingAlarmIntent(Context context, Alarm alarm, boolean retrievePrevious) {
|
private static PendingIntent notifyUpcomingAlarmIntent(Context context, Alarm alarm, boolean retrievePrevious) {
|
||||||
Intent intent = new Intent(context, UpcomingAlarmReceiver.class)
|
Intent intent = new Intent(context, UpcomingAlarmReceiver.class)
|
||||||
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM_ID, alarm.id());
|
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, alarm);
|
||||||
if (alarm.isSnoozed()) {
|
if (alarm.isSnoozed()) {
|
||||||
// TODO: Will this affect retrieving a previous instance? Say if the previous instance
|
// 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
|
// didn't have this action set initially, but at a later time we made a new instance
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user