Add AlarmManager

pull/321/head
Alex Baker 9 years ago
parent 93168ce3e1
commit a7765bccf2

@ -9,10 +9,12 @@ import org.joda.time.DateTime;
import org.tasks.Freeze; import org.tasks.Freeze;
import org.tasks.R; import org.tasks.R;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.scheduling.AlarmManager;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.todoroo.astrid.reminders.ReminderService.NO_ALARM; import static com.todoroo.astrid.reminders.ReminderService.NO_ALARM;
import static org.mockito.Mockito.mock;
import static org.tasks.Freeze.freezeAt; import static org.tasks.Freeze.freezeAt;
import static org.tasks.Freeze.thaw; import static org.tasks.Freeze.thaw;
import static org.tasks.date.DateTimeUtils.newDate; import static org.tasks.date.DateTimeUtils.newDate;
@ -33,7 +35,7 @@ public class NotifyAtDeadlineTest extends AndroidTestCase {
@Override @Override
public void setUp() { public void setUp() {
preferences = new Preferences(getContext(), null); preferences = new Preferences(getContext(), null);
reminderService = new ReminderService(getContext(), preferences); reminderService = new ReminderService(getContext(), preferences, mock(AlarmManager.class));
freezeAt(new DateTime(2014, 1, 24, 17, 23, 37)); freezeAt(new DateTime(2014, 1, 24, 17, 23, 37));
} }

@ -5,7 +5,6 @@
*/ */
package com.todoroo.astrid.alarms; package com.todoroo.astrid.alarms;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
@ -27,6 +26,7 @@ import com.todoroo.astrid.service.SynchronizeMetadataCallback;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.receivers.TaskNotificationReceiver; import org.tasks.receivers.TaskNotificationReceiver;
import org.tasks.scheduling.AlarmManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
@ -50,6 +50,7 @@ public class AlarmService {
private final MetadataDao metadataDao; private final MetadataDao metadataDao;
private final Context context; private final Context context;
private final AlarmManager alarmManager;
private final Callback<Metadata> scheduleAlarm = new Callback<Metadata>() { private final Callback<Metadata> scheduleAlarm = new Callback<Metadata>() {
@Override @Override
public void apply(Metadata alarm) { public void apply(Metadata alarm) {
@ -58,9 +59,10 @@ public class AlarmService {
}; };
@Inject @Inject
public AlarmService(MetadataDao metadataDao, @ForApplication Context context) { public AlarmService(MetadataDao metadataDao, @ForApplication Context context, AlarmManager alarmManager) {
this.metadataDao = metadataDao; this.metadataDao = metadataDao;
this.context = context; this.context = context;
this.alarmManager = alarmManager;
} }
public void getAlarms(long taskId, Callback<Metadata> callback) { public void getAlarms(long taskId, Callback<Metadata> callback) {
@ -83,14 +85,12 @@ public class AlarmService {
metadata.add(item); metadata.add(item);
} }
final AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
boolean changed = synchronizeMetadata(taskId, metadata, new SynchronizeMetadataCallback() { boolean changed = synchronizeMetadata(taskId, metadata, new SynchronizeMetadataCallback() {
@Override @Override
public void beforeDeleteMetadata(Metadata m) { public void beforeDeleteMetadata(Metadata m) {
// Cancel the alarm before the metadata is deleted // Cancel the alarm before the metadata is deleted
PendingIntent pendingIntent = pendingIntentForAlarm(m, taskId); PendingIntent pendingIntent = pendingIntentForAlarm(m, taskId);
am.cancel(pendingIntent); alarmManager.cancel(pendingIntent);
} }
}); });
@ -149,14 +149,13 @@ public class AlarmService {
long taskId = alarm.getTask(); long taskId = alarm.getTask();
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = pendingIntentForAlarm(alarm, taskId); PendingIntent pendingIntent = pendingIntentForAlarm(alarm, taskId);
long time = alarm.getValue(AlarmFields.TIME); long time = alarm.getValue(AlarmFields.TIME);
if(time == 0 || time == NO_ALARM) { if(time == 0 || time == NO_ALARM) {
am.cancel(pendingIntent); alarmManager.cancel(pendingIntent);
} else if(time > DateUtilities.now()) { } else if(time > DateUtilities.now()) {
am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent); alarmManager.wakeup(time, pendingIntent);
} }
} }

@ -1,6 +1,5 @@
package com.todoroo.astrid.gcal; package com.todoroo.astrid.gcal;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
@ -12,6 +11,7 @@ import com.todoroo.andlib.utility.DateUtilities;
import org.tasks.R; import org.tasks.R;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.scheduling.AlarmManager;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -23,10 +23,12 @@ public class CalendarAlarmScheduler {
public static final String URI_PREFIX_POSTPONE = "cal-postpone"; public static final String URI_PREFIX_POSTPONE = "cal-postpone";
private final Preferences preferences; private final Preferences preferences;
private AlarmManager alarmManager;
@Inject @Inject
public CalendarAlarmScheduler(Preferences preferences) { public CalendarAlarmScheduler(Preferences preferences, AlarmManager alarmManager) {
this.preferences = preferences; this.preferences = preferences;
this.alarmManager = alarmManager;
} }
public void scheduleCalendarAlarms(final Context context, boolean force) { public void scheduleCalendarAlarms(final Context context, boolean force) {
@ -50,7 +52,6 @@ public class CalendarAlarmScheduler {
long now = DateUtilities.now(); long now = DateUtilities.now();
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Cursor events = cr.query(Calendars.getCalendarContentUri(Calendars.CALENDAR_CONTENT_EVENTS), Cursor events = cr.query(Calendars.getCalendarContentUri(Calendars.CALENDAR_CONTENT_EVENTS),
new String[] { Calendars.ID_COLUMN_NAME, Calendars.EVENTS_DTSTART_COL }, new String[] { Calendars.ID_COLUMN_NAME, Calendars.EVENTS_DTSTART_COL },
Calendars.EVENTS_DTSTART_COL + " > ? AND " + Calendars.EVENTS_DTSTART_COL + " < ?", Calendars.EVENTS_DTSTART_COL + " > ? AND " + Calendars.EVENTS_DTSTART_COL + " < ?",
@ -73,10 +74,10 @@ public class CalendarAlarmScheduler {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
CalendarAlarmReceiver.REQUEST_CODE_CAL_REMINDER, eventAlarm, 0); CalendarAlarmReceiver.REQUEST_CODE_CAL_REMINDER, eventAlarm, 0);
am.cancel(pendingIntent); alarmManager.cancel(pendingIntent);
long alarmTime = start - DateUtilities.ONE_MINUTE * 15; long alarmTime = start - DateUtilities.ONE_MINUTE * 15;
am.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent); alarmManager.wakeup(alarmTime, pendingIntent);
} }
} }
@ -84,8 +85,8 @@ public class CalendarAlarmScheduler {
Intent rescheduleAlarm = new Intent(CalendarStartupReceiver.BROADCAST_RESCHEDULE_CAL_ALARMS); Intent rescheduleAlarm = new Intent(CalendarStartupReceiver.BROADCAST_RESCHEDULE_CAL_ALARMS);
PendingIntent pendingReschedule = PendingIntent.getBroadcast(context, 0, PendingIntent pendingReschedule = PendingIntent.getBroadcast(context, 0,
rescheduleAlarm, 0); rescheduleAlarm, 0);
am.cancel(pendingReschedule); alarmManager.cancel(pendingReschedule);
am.set(AlarmManager.RTC, DateUtilities.now() + DateUtilities.ONE_HOUR * 12, pendingReschedule); alarmManager.noWakeup(DateUtilities.now() + DateUtilities.ONE_HOUR * 12, pendingReschedule);
} finally { } finally {
if (events != null) { if (events != null) {
events.close(); events.close();

@ -1,6 +1,5 @@
package com.todoroo.astrid.gcal; package com.todoroo.astrid.gcal;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -28,6 +27,7 @@ import com.todoroo.astrid.tags.TagFilterExposer;
import org.tasks.R; import org.tasks.R;
import org.tasks.preferences.ActivityPreferences; import org.tasks.preferences.ActivityPreferences;
import org.tasks.preferences.ResourceResolver; import org.tasks.preferences.ResourceResolver;
import org.tasks.scheduling.AlarmManager;
import javax.inject.Inject; import javax.inject.Inject;
@ -54,6 +54,7 @@ public class CalendarReminderActivity extends InjectingAppCompatActivity {
@Inject ActivityPreferences preferences; @Inject ActivityPreferences preferences;
@Inject ResourceResolver resourceResolver; @Inject ResourceResolver resourceResolver;
@Inject DialogBuilder dialogBuilder; @Inject DialogBuilder dialogBuilder;
@Inject AlarmManager alarmManager;
private String eventName; private String eventName;
private long startTime; private long startTime;
@ -224,8 +225,6 @@ public class CalendarReminderActivity extends InjectingAppCompatActivity {
} }
private void postpone() { private void postpone() {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent eventAlarm = new Intent(this, CalendarAlarmReceiver.class); Intent eventAlarm = new Intent(this, CalendarAlarmReceiver.class);
eventAlarm.setAction(CalendarAlarmReceiver.BROADCAST_CALENDAR_REMINDER); eventAlarm.setAction(CalendarAlarmReceiver.BROADCAST_CALENDAR_REMINDER);
eventAlarm.setData(Uri.parse(CalendarAlarmScheduler.URI_PREFIX_POSTPONE + "://" + eventId)); eventAlarm.setData(Uri.parse(CalendarAlarmScheduler.URI_PREFIX_POSTPONE + "://" + eventId));
@ -233,10 +232,10 @@ public class CalendarReminderActivity extends InjectingAppCompatActivity {
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
CalendarAlarmReceiver.REQUEST_CODE_CAL_REMINDER, eventAlarm, 0); CalendarAlarmReceiver.REQUEST_CODE_CAL_REMINDER, eventAlarm, 0);
am.cancel(pendingIntent); alarmManager.cancel(pendingIntent);
long alarmTime = endTime + DateUtilities.ONE_MINUTE * 5; long alarmTime = endTime + DateUtilities.ONE_MINUTE * 5;
am.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent); alarmManager.wakeup(alarmTime, pendingIntent);
dismissButton.performClick(); dismissButton.performClick();
} }

@ -5,7 +5,6 @@
*/ */
package com.todoroo.astrid.reminders; package com.todoroo.astrid.reminders;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -26,6 +25,7 @@ import org.tasks.R;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.receivers.TaskNotificationReceiver; import org.tasks.receivers.TaskNotificationReceiver;
import org.tasks.scheduling.AlarmManager;
import java.util.Random; import java.util.Random;
@ -76,16 +76,17 @@ public final class ReminderService {
// --- instance variables // --- instance variables
private AlarmScheduler scheduler = new ReminderAlarmScheduler(); private AlarmScheduler scheduler;
private long now = -1; // For tracking when reminders might be scheduled all at once private long now = -1; // For tracking when reminders might be scheduled all at once
private Context context; private Context context;
private Preferences preferences; private Preferences preferences;
@Inject @Inject
ReminderService(@ForApplication Context context, Preferences preferences) { ReminderService(@ForApplication Context context, Preferences preferences, AlarmManager alarmManager) {
this.context = context; this.context = context;
this.preferences = preferences; this.preferences = preferences;
scheduler = new ReminderAlarmScheduler(alarmManager);
} }
private static final int MILLIS_PER_HOUR = 60 * 60 * 1000; private static final int MILLIS_PER_HOUR = 60 * 60 * 1000;
@ -397,6 +398,12 @@ public final class ReminderService {
} }
private static class ReminderAlarmScheduler implements AlarmScheduler { private static class ReminderAlarmScheduler implements AlarmScheduler {
private final AlarmManager alarmManager;
public ReminderAlarmScheduler(AlarmManager alarmManager) {
this.alarmManager = alarmManager;
}
/** /**
* Create an alarm for the given task at the given type * Create an alarm for the given task at the given type
*/ */
@ -421,18 +428,17 @@ public final class ReminderService {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
requestCode = type; requestCode = type;
} }
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode,
intent, 0); intent, 0);
if (time == 0 || time == NO_ALARM) { if (time == 0 || time == NO_ALARM) {
am.cancel(pendingIntent); alarmManager.cancel(pendingIntent);
} else { } else {
if(time < DateUtilities.now()) { if(time < DateUtilities.now()) {
time = DateUtilities.now() + 5000L; time = DateUtilities.now() + 5000L;
} }
am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent); alarmManager.wakeup(time, pendingIntent);
} }
} }
} }

@ -0,0 +1,34 @@
package org.tasks.scheduling;
import android.app.PendingIntent;
import android.content.Context;
import org.tasks.injection.ForApplication;
import javax.inject.Inject;
public class AlarmManager {
private final android.app.AlarmManager alarmManager;
@Inject
public AlarmManager(@ForApplication Context context) {
alarmManager = (android.app.AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
public void cancel(PendingIntent pendingIntent) {
alarmManager.cancel(pendingIntent);
}
public void wakeup(long time, PendingIntent pendingIntent) {
alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent);
}
public void noWakeup(long time, PendingIntent pendingIntent) {
alarmManager.set(android.app.AlarmManager.RTC, time, pendingIntent);
}
public void setInexactRepeating(long interval, PendingIntent pendingIntent) {
alarmManager.setInexactRepeating(android.app.AlarmManager.RTC, 0, interval, pendingIntent);
}
}

@ -1,8 +1,6 @@
package org.tasks.scheduling; package org.tasks.scheduling;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -24,6 +22,7 @@ public abstract class MidnightIntentService extends InjectingIntentService {
private static final long PADDING = SECONDS.toMillis(1); private static final long PADDING = SECONDS.toMillis(1);
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject AlarmManager alarmManager;
public MidnightIntentService(String name) { public MidnightIntentService(String name) {
super(name); super(name);
@ -46,9 +45,8 @@ public abstract class MidnightIntentService extends InjectingIntentService {
log.debug("will run at {} [lastRun={}]", printTimestamp(nextRun), printTimestamp(lastRun)); log.debug("will run at {} [lastRun={}]", printTimestamp(nextRun), printTimestamp(lastRun));
} }
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, new Intent(this, this.getClass()), PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent = PendingIntent.getService(this, 0, new Intent(this, this.getClass()), PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC, nextRun + PADDING, pendingIntent); alarmManager.noWakeup(nextRun + PADDING, pendingIntent);
} }
private static long nextMidnight(long timestamp) { private static long nextMidnight(long timestamp) {

@ -1,8 +1,6 @@
package org.tasks.scheduling; package org.tasks.scheduling;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -23,6 +21,7 @@ public abstract class RecurringIntervalIntentService extends InjectingIntentServ
private static final long PADDING = SECONDS.toMillis(1); private static final long PADDING = SECONDS.toMillis(1);
@Inject Preferences preferences; @Inject Preferences preferences;
@Inject AlarmManager alarmManager;
public RecurringIntervalIntentService(String name) { public RecurringIntervalIntentService(String name) {
super(name); super(name);
@ -52,9 +51,8 @@ public abstract class RecurringIntervalIntentService extends InjectingIntentServ
log.debug("will run at {} [lastRun={}]", printTimestamp(nextRun), printTimestamp(lastRun)); log.debug("will run at {} [lastRun={}]", printTimestamp(nextRun), printTimestamp(lastRun));
} }
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, new Intent(this, this.getClass()), PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent = PendingIntent.getService(this, 0, new Intent(this, this.getClass()), PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC, nextRun, pendingIntent); alarmManager.noWakeup(nextRun, pendingIntent);
} }
abstract void run(); abstract void run();

@ -1,6 +1,5 @@
package org.tasks.scheduling; package org.tasks.scheduling;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -27,6 +26,7 @@ public class RefreshScheduler {
private final TaskDao taskDao; private final TaskDao taskDao;
private final Context context; private final Context context;
private final AlarmManager alarmManager;
private static final Property<?>[] REFRESH_PROPERTIES = new Property<?>[]{ private static final Property<?>[] REFRESH_PROPERTIES = new Property<?>[]{
Task.DUE_DATE, Task.DUE_DATE,
@ -34,9 +34,10 @@ public class RefreshScheduler {
}; };
@Inject @Inject
public RefreshScheduler(TaskDao taskDao, @ForApplication Context context) { public RefreshScheduler(TaskDao taskDao, @ForApplication Context context, AlarmManager alarmManager) {
this.taskDao = taskDao; this.taskDao = taskDao;
this.context = context; this.context = context;
this.alarmManager = alarmManager;
} }
public void scheduleApplicationRefreshes() { public void scheduleApplicationRefreshes() {
@ -71,9 +72,8 @@ public class RefreshScheduler {
dueDate += 1000; // this is ghetto dueDate += 1000; // this is ghetto
Intent intent = new Intent(context, RefreshReceiver.class); Intent intent = new Intent(context, RefreshReceiver.class);
intent.setAction(Long.toString(dueDate)); intent.setAction(Long.toString(dueDate));
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT);
am.set(AlarmManager.RTC, dueDate, pendingIntent); alarmManager.noWakeup(dueDate, pendingIntent);
} }
private TodorooCursor<Task> getTasks() { private TodorooCursor<Task> getTasks() {

@ -1,7 +1,6 @@
package org.tasks.widget; package org.tasks.widget;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManager;
import android.content.ComponentName; import android.content.ComponentName;
@ -28,8 +27,8 @@ import com.todoroo.astrid.widget.WidgetConfigActivity;
import org.tasks.R; import org.tasks.R;
import org.tasks.intents.TaskIntents; import org.tasks.intents.TaskIntents;
import org.tasks.preferences.ActivityPreferences;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.scheduling.AlarmManager;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -46,19 +45,20 @@ public class WidgetHelper {
private final TagDataDao tagDataDao; private final TagDataDao tagDataDao;
private final Preferences preferences; private final Preferences preferences;
private AlarmManager alarmManager;
@Inject @Inject
public WidgetHelper(TagDataDao tagDataDao, Preferences preferences) { public WidgetHelper(TagDataDao tagDataDao, Preferences preferences, AlarmManager alarmManager) {
this.tagDataDao = tagDataDao; this.tagDataDao = tagDataDao;
this.preferences = preferences; this.preferences = preferences;
this.alarmManager = alarmManager;
} }
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public RemoteViews createScrollableWidget(Context context, int id) { public RemoteViews createScrollableWidget(Context context, int id) {
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, ScrollableWidgetUpdateService.class); Intent intent = new Intent(context, ScrollableWidgetUpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setInexactRepeating(AlarmManager.RTC, 0, TimeUnit.MINUTES.toMillis(30), pendingIntent); alarmManager.setInexactRepeating(TimeUnit.MINUTES.toMillis(30), pendingIntent);
Filter filter = getFilter(context, id); Filter filter = getFilter(context, id);
Intent rvIntent = new Intent(context, ScrollableWidgetUpdateService.class); Intent rvIntent = new Intent(context, ScrollableWidgetUpdateService.class);

Loading…
Cancel
Save