diff --git a/src/androidTest/java/com/todoroo/astrid/reminders/NotifyAtDeadlineTest.java b/src/androidTest/java/com/todoroo/astrid/reminders/NotifyAtDeadlineTest.java index cc14fedc7..ee55807ec 100644 --- a/src/androidTest/java/com/todoroo/astrid/reminders/NotifyAtDeadlineTest.java +++ b/src/androidTest/java/com/todoroo/astrid/reminders/NotifyAtDeadlineTest.java @@ -9,10 +9,12 @@ import org.joda.time.DateTime; import org.tasks.Freeze; import org.tasks.R; import org.tasks.preferences.Preferences; +import org.tasks.scheduling.AlarmManager; import java.util.concurrent.TimeUnit; 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.thaw; import static org.tasks.date.DateTimeUtils.newDate; @@ -33,7 +35,7 @@ public class NotifyAtDeadlineTest extends AndroidTestCase { @Override public void setUp() { 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)); } diff --git a/src/main/java/com/todoroo/astrid/alarms/AlarmService.java b/src/main/java/com/todoroo/astrid/alarms/AlarmService.java index 923b396d2..414995f11 100644 --- a/src/main/java/com/todoroo/astrid/alarms/AlarmService.java +++ b/src/main/java/com/todoroo/astrid/alarms/AlarmService.java @@ -5,7 +5,6 @@ */ package com.todoroo.astrid.alarms; -import android.app.AlarmManager; import android.app.PendingIntent; import android.content.ContentValues; import android.content.Context; @@ -27,6 +26,7 @@ import com.todoroo.astrid.service.SynchronizeMetadataCallback; import org.tasks.injection.ForApplication; import org.tasks.receivers.TaskNotificationReceiver; +import org.tasks.scheduling.AlarmManager; import java.util.ArrayList; import java.util.HashSet; @@ -50,6 +50,7 @@ public class AlarmService { private final MetadataDao metadataDao; private final Context context; + private final AlarmManager alarmManager; private final Callback scheduleAlarm = new Callback() { @Override public void apply(Metadata alarm) { @@ -58,9 +59,10 @@ public class AlarmService { }; @Inject - public AlarmService(MetadataDao metadataDao, @ForApplication Context context) { + public AlarmService(MetadataDao metadataDao, @ForApplication Context context, AlarmManager alarmManager) { this.metadataDao = metadataDao; this.context = context; + this.alarmManager = alarmManager; } public void getAlarms(long taskId, Callback callback) { @@ -83,14 +85,12 @@ public class AlarmService { metadata.add(item); } - final AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); - boolean changed = synchronizeMetadata(taskId, metadata, new SynchronizeMetadataCallback() { @Override public void beforeDeleteMetadata(Metadata m) { // Cancel the alarm before the metadata is deleted PendingIntent pendingIntent = pendingIntentForAlarm(m, taskId); - am.cancel(pendingIntent); + alarmManager.cancel(pendingIntent); } }); @@ -149,14 +149,13 @@ public class AlarmService { long taskId = alarm.getTask(); - AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); PendingIntent pendingIntent = pendingIntentForAlarm(alarm, taskId); long time = alarm.getValue(AlarmFields.TIME); if(time == 0 || time == NO_ALARM) { - am.cancel(pendingIntent); + alarmManager.cancel(pendingIntent); } else if(time > DateUtilities.now()) { - am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent); + alarmManager.wakeup(time, pendingIntent); } } diff --git a/src/main/java/com/todoroo/astrid/gcal/CalendarAlarmScheduler.java b/src/main/java/com/todoroo/astrid/gcal/CalendarAlarmScheduler.java index e41813835..b6625881e 100644 --- a/src/main/java/com/todoroo/astrid/gcal/CalendarAlarmScheduler.java +++ b/src/main/java/com/todoroo/astrid/gcal/CalendarAlarmScheduler.java @@ -1,6 +1,5 @@ package com.todoroo.astrid.gcal; -import android.app.AlarmManager; import android.app.PendingIntent; import android.content.ContentResolver; import android.content.Context; @@ -12,6 +11,7 @@ import com.todoroo.andlib.utility.DateUtilities; import org.tasks.R; import org.tasks.preferences.Preferences; +import org.tasks.scheduling.AlarmManager; import javax.inject.Inject; import javax.inject.Singleton; @@ -23,10 +23,12 @@ public class CalendarAlarmScheduler { public static final String URI_PREFIX_POSTPONE = "cal-postpone"; private final Preferences preferences; + private AlarmManager alarmManager; @Inject - public CalendarAlarmScheduler(Preferences preferences) { + public CalendarAlarmScheduler(Preferences preferences, AlarmManager alarmManager) { this.preferences = preferences; + this.alarmManager = alarmManager; } public void scheduleCalendarAlarms(final Context context, boolean force) { @@ -50,7 +52,6 @@ public class CalendarAlarmScheduler { long now = DateUtilities.now(); - AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); Cursor events = cr.query(Calendars.getCalendarContentUri(Calendars.CALENDAR_CONTENT_EVENTS), new String[] { Calendars.ID_COLUMN_NAME, 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, CalendarAlarmReceiver.REQUEST_CODE_CAL_REMINDER, eventAlarm, 0); - am.cancel(pendingIntent); + alarmManager.cancel(pendingIntent); 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); PendingIntent pendingReschedule = PendingIntent.getBroadcast(context, 0, rescheduleAlarm, 0); - am.cancel(pendingReschedule); - am.set(AlarmManager.RTC, DateUtilities.now() + DateUtilities.ONE_HOUR * 12, pendingReschedule); + alarmManager.cancel(pendingReschedule); + alarmManager.noWakeup(DateUtilities.now() + DateUtilities.ONE_HOUR * 12, pendingReschedule); } finally { if (events != null) { events.close(); diff --git a/src/main/java/com/todoroo/astrid/gcal/CalendarReminderActivity.java b/src/main/java/com/todoroo/astrid/gcal/CalendarReminderActivity.java index 128de42b6..fdb199da2 100644 --- a/src/main/java/com/todoroo/astrid/gcal/CalendarReminderActivity.java +++ b/src/main/java/com/todoroo/astrid/gcal/CalendarReminderActivity.java @@ -1,6 +1,5 @@ package com.todoroo.astrid.gcal; -import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.DialogInterface; @@ -28,6 +27,7 @@ import com.todoroo.astrid.tags.TagFilterExposer; import org.tasks.R; import org.tasks.preferences.ActivityPreferences; import org.tasks.preferences.ResourceResolver; +import org.tasks.scheduling.AlarmManager; import javax.inject.Inject; @@ -54,6 +54,7 @@ public class CalendarReminderActivity extends InjectingAppCompatActivity { @Inject ActivityPreferences preferences; @Inject ResourceResolver resourceResolver; @Inject DialogBuilder dialogBuilder; + @Inject AlarmManager alarmManager; private String eventName; private long startTime; @@ -224,8 +225,6 @@ public class CalendarReminderActivity extends InjectingAppCompatActivity { } private void postpone() { - AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); - Intent eventAlarm = new Intent(this, CalendarAlarmReceiver.class); eventAlarm.setAction(CalendarAlarmReceiver.BROADCAST_CALENDAR_REMINDER); eventAlarm.setData(Uri.parse(CalendarAlarmScheduler.URI_PREFIX_POSTPONE + "://" + eventId)); @@ -233,10 +232,10 @@ public class CalendarReminderActivity extends InjectingAppCompatActivity { PendingIntent pendingIntent = PendingIntent.getBroadcast(this, CalendarAlarmReceiver.REQUEST_CODE_CAL_REMINDER, eventAlarm, 0); - am.cancel(pendingIntent); + alarmManager.cancel(pendingIntent); long alarmTime = endTime + DateUtilities.ONE_MINUTE * 5; - am.set(AlarmManager.RTC_WAKEUP, alarmTime, pendingIntent); + alarmManager.wakeup(alarmTime, pendingIntent); dismissButton.performClick(); } diff --git a/src/main/java/com/todoroo/astrid/reminders/ReminderService.java b/src/main/java/com/todoroo/astrid/reminders/ReminderService.java index 248d4c2b7..7889c60fa 100644 --- a/src/main/java/com/todoroo/astrid/reminders/ReminderService.java +++ b/src/main/java/com/todoroo/astrid/reminders/ReminderService.java @@ -5,7 +5,6 @@ */ package com.todoroo.astrid.reminders; -import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; @@ -26,6 +25,7 @@ import org.tasks.R; import org.tasks.injection.ForApplication; import org.tasks.preferences.Preferences; import org.tasks.receivers.TaskNotificationReceiver; +import org.tasks.scheduling.AlarmManager; import java.util.Random; @@ -76,16 +76,17 @@ public final class ReminderService { // --- 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 Context context; private Preferences preferences; @Inject - ReminderService(@ForApplication Context context, Preferences preferences) { + ReminderService(@ForApplication Context context, Preferences preferences, AlarmManager alarmManager) { this.context = context; this.preferences = preferences; + scheduler = new ReminderAlarmScheduler(alarmManager); } 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 final AlarmManager alarmManager; + + public ReminderAlarmScheduler(AlarmManager alarmManager) { + this.alarmManager = alarmManager; + } + /** * Create an alarm for the given task at the given type */ @@ -421,18 +428,17 @@ public final class ReminderService { log.error(e.getMessage(), e); requestCode = type; } - AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, 0); if (time == 0 || time == NO_ALARM) { - am.cancel(pendingIntent); + alarmManager.cancel(pendingIntent); } else { if(time < DateUtilities.now()) { time = DateUtilities.now() + 5000L; } - am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent); + alarmManager.wakeup(time, pendingIntent); } } } diff --git a/src/main/java/org/tasks/scheduling/AlarmManager.java b/src/main/java/org/tasks/scheduling/AlarmManager.java new file mode 100644 index 000000000..2a48e557b --- /dev/null +++ b/src/main/java/org/tasks/scheduling/AlarmManager.java @@ -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); + } +} diff --git a/src/main/java/org/tasks/scheduling/MidnightIntentService.java b/src/main/java/org/tasks/scheduling/MidnightIntentService.java index 4a5e99018..395da1fb1 100644 --- a/src/main/java/org/tasks/scheduling/MidnightIntentService.java +++ b/src/main/java/org/tasks/scheduling/MidnightIntentService.java @@ -1,8 +1,6 @@ package org.tasks.scheduling; -import android.app.AlarmManager; import android.app.PendingIntent; -import android.content.Context; import android.content.Intent; import org.slf4j.Logger; @@ -24,6 +22,7 @@ public abstract class MidnightIntentService extends InjectingIntentService { private static final long PADDING = SECONDS.toMillis(1); @Inject Preferences preferences; + @Inject AlarmManager alarmManager; public MidnightIntentService(String name) { super(name); @@ -46,9 +45,8 @@ public abstract class MidnightIntentService extends InjectingIntentService { 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); - alarmManager.set(AlarmManager.RTC, nextRun + PADDING, pendingIntent); + alarmManager.noWakeup(nextRun + PADDING, pendingIntent); } private static long nextMidnight(long timestamp) { diff --git a/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java b/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java index 6f027b1ed..a5fe05bab 100644 --- a/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java +++ b/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java @@ -1,8 +1,6 @@ package org.tasks.scheduling; -import android.app.AlarmManager; import android.app.PendingIntent; -import android.content.Context; import android.content.Intent; import org.slf4j.Logger; @@ -23,6 +21,7 @@ public abstract class RecurringIntervalIntentService extends InjectingIntentServ private static final long PADDING = SECONDS.toMillis(1); @Inject Preferences preferences; + @Inject AlarmManager alarmManager; public RecurringIntervalIntentService(String name) { super(name); @@ -52,9 +51,8 @@ public abstract class RecurringIntervalIntentService extends InjectingIntentServ 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); - alarmManager.set(AlarmManager.RTC, nextRun, pendingIntent); + alarmManager.noWakeup(nextRun, pendingIntent); } abstract void run(); diff --git a/src/main/java/org/tasks/scheduling/RefreshScheduler.java b/src/main/java/org/tasks/scheduling/RefreshScheduler.java index eb991dd95..c7d2b1b99 100644 --- a/src/main/java/org/tasks/scheduling/RefreshScheduler.java +++ b/src/main/java/org/tasks/scheduling/RefreshScheduler.java @@ -1,6 +1,5 @@ package org.tasks.scheduling; -import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; @@ -27,6 +26,7 @@ public class RefreshScheduler { private final TaskDao taskDao; private final Context context; + private final AlarmManager alarmManager; private static final Property[] REFRESH_PROPERTIES = new Property[]{ Task.DUE_DATE, @@ -34,9 +34,10 @@ public class RefreshScheduler { }; @Inject - public RefreshScheduler(TaskDao taskDao, @ForApplication Context context) { + public RefreshScheduler(TaskDao taskDao, @ForApplication Context context, AlarmManager alarmManager) { this.taskDao = taskDao; this.context = context; + this.alarmManager = alarmManager; } public void scheduleApplicationRefreshes() { @@ -71,9 +72,8 @@ public class RefreshScheduler { dueDate += 1000; // this is ghetto Intent intent = new Intent(context, RefreshReceiver.class); intent.setAction(Long.toString(dueDate)); - AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT); - am.set(AlarmManager.RTC, dueDate, pendingIntent); + alarmManager.noWakeup(dueDate, pendingIntent); } private TodorooCursor getTasks() { diff --git a/src/main/java/org/tasks/widget/WidgetHelper.java b/src/main/java/org/tasks/widget/WidgetHelper.java index b2ed2100f..6be210ee1 100644 --- a/src/main/java/org/tasks/widget/WidgetHelper.java +++ b/src/main/java/org/tasks/widget/WidgetHelper.java @@ -1,7 +1,6 @@ package org.tasks.widget; import android.annotation.TargetApi; -import android.app.AlarmManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.content.ComponentName; @@ -28,8 +27,8 @@ import com.todoroo.astrid.widget.WidgetConfigActivity; import org.tasks.R; import org.tasks.intents.TaskIntents; -import org.tasks.preferences.ActivityPreferences; import org.tasks.preferences.Preferences; +import org.tasks.scheduling.AlarmManager; import java.util.concurrent.TimeUnit; @@ -46,19 +45,20 @@ public class WidgetHelper { private final TagDataDao tagDataDao; private final Preferences preferences; + private AlarmManager alarmManager; @Inject - public WidgetHelper(TagDataDao tagDataDao, Preferences preferences) { + public WidgetHelper(TagDataDao tagDataDao, Preferences preferences, AlarmManager alarmManager) { this.tagDataDao = tagDataDao; this.preferences = preferences; + this.alarmManager = alarmManager; } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public RemoteViews createScrollableWidget(Context context, int id) { - AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, ScrollableWidgetUpdateService.class); 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); Intent rvIntent = new Intent(context, ScrollableWidgetUpdateService.class);