diff --git a/astrid/plugin-src/com/todoroo/astrid/alarms/AlarmService.java b/astrid/plugin-src/com/todoroo/astrid/alarms/AlarmService.java index abe6d3f69..c9427e68d 100644 --- a/astrid/plugin-src/com/todoroo/astrid/alarms/AlarmService.java +++ b/astrid/plugin-src/com/todoroo/astrid/alarms/AlarmService.java @@ -1,14 +1,27 @@ package com.todoroo.astrid.alarms; +import java.util.Date; import java.util.LinkedHashSet; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.sql.Criterion; +import com.todoroo.andlib.sql.Join; import com.todoroo.andlib.sql.Order; import com.todoroo.andlib.sql.Query; import com.todoroo.astrid.core.PluginServices; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; +import com.todoroo.astrid.dao.TaskDao.TaskCriteria; import com.todoroo.astrid.model.Metadata; +import com.todoroo.astrid.model.Task; +import com.todoroo.astrid.reminders.Notifications; +import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.service.MetadataService; /** @@ -29,7 +42,7 @@ public class AlarmService { return instance; } - // --- interface + // --- data retrieval /** * Return alarms for the given task. PLEASE CLOSE THE CURSOR! @@ -62,4 +75,103 @@ public class AlarmService { service.save(metadata); } } + + // --- alarm scheduling + + /** + * Gets a listing of all alarms that are active + * @param properties + * @return todoroo cursor. PLEASE CLOSE THIS CURSOR! + */ + private TodorooCursor getActiveAlarms() { + return PluginServices.getMetadataService().query(Query.select(Alarm.TIME). + join(Join.inner(Task.TABLE, Metadata.TASK.eq(Task.ID))). + where(Criterion.and(TaskCriteria.isActive(), MetadataCriteria.withKey(Alarm.METADATA_KEY)))); + } + + /** + * Gets a listing of alarms by task + * @param properties + * @return todoroo cursor. PLEASE CLOSE THIS CURSOR! + */ + private TodorooCursor getAlarmsForTask(long taskId) { + return PluginServices.getMetadataService().query(Query.select(Alarm.TIME). + join(Join.inner(Task.TABLE, Metadata.TASK.eq(Task.ID))). + where(Criterion.and(TaskCriteria.isActive(), + MetadataCriteria.byTaskAndwithKey(taskId, Alarm.METADATA_KEY)))); + } + + /** + * Schedules all alarms + */ + public void scheduleAllAlarms() { + TodorooCursor cursor = getActiveAlarms(); + try { + Metadata alarm = new Metadata(); + for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { + alarm.readFromCursor(cursor); + scheduleAlarm(alarm); + } + } catch (Exception e) { + // suppress + } finally { + cursor.close(); + } + } + + private static final long NO_ALARM = Long.MAX_VALUE; + + /** + * Schedules alarms for a single task + * @param task + */ + public void scheduleAlarms(Task task) { + TodorooCursor cursor = getAlarmsForTask(task.getId()); + try { + Metadata alarm = new Metadata(); + for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { + alarm.readFromCursor(cursor); + scheduleAlarm(alarm); + } + } catch (Exception e) { + // suppress + } finally { + cursor.close(); + } + } + + /** + * Schedules alarms for a single task + * + * @param shouldPerformPropertyCheck + * whether to check if task has requisite properties + */ + @SuppressWarnings("nls") + private void scheduleAlarm(Metadata alarm) { + if(alarm == null) + return; + + long taskId = alarm.getValue(Metadata.TASK); + int type = ReminderService.TYPE_ALARM; + + Context context = ContextManager.getContext(); + Intent intent = new Intent(context, Notifications.class); + intent.setType("ALARM" + Long.toString(taskId)); //$NON-NLS-1$ + intent.setAction(Integer.toString(type)); + intent.putExtra(Notifications.ID_KEY, taskId); + intent.putExtra(Notifications.TYPE_KEY, type); + + AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, + intent, 0); + + long time = alarm.getValue(Alarm.TIME); + if(time == 0 || time == NO_ALARM) + am.cancel(pendingIntent); + else { + Log.e("Astrid", "Alarm (" + taskId + ", " + type + + ") set for " + new Date(time)); + am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent); + } + } } diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java b/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java index 0a55040ce..4ef8ed559 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java @@ -32,10 +32,10 @@ public class Notifications extends BroadcastReceiver { // --- constants /** task id extra */ - static final String ID_KEY = "id"; //$NON-NLS-1$ + public static final String ID_KEY = "id"; //$NON-NLS-1$ /** notification type extra */ - static final String TYPE_KEY = "type"; //$NON-NLS-1$ + public static final String TYPE_KEY = "type"; //$NON-NLS-1$ /** preference values */ public static final int ICON_SET_PINK = 0; diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderService.java b/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderService.java index 3fe029a8a..68f7099b9 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderService.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderService.java @@ -46,13 +46,15 @@ public final class ReminderService { }; /** flag for due date reminder */ - static final int TYPE_DUE = 0; + public static final int TYPE_DUE = 0; /** flag for overdue reminder */ - static final int TYPE_OVERDUE = 1; + public static final int TYPE_OVERDUE = 1; /** flag for random reminder */ - static final int TYPE_RANDOM = 2; + public static final int TYPE_RANDOM = 2; /** flag for a snoozed reminder */ - static final int TYPE_SNOOZE = 3; + public static final int TYPE_SNOOZE = 3; + /** flag for an alarm reminder */ + public static final int TYPE_ALARM = 4; static final Random random = new Random(); diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderStartupReceiver.java b/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderStartupReceiver.java index f76aa32d2..a210bbed0 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderStartupReceiver.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/ReminderStartupReceiver.java @@ -8,6 +8,7 @@ import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.service.ExceptionService; +import com.todoroo.astrid.alarms.AlarmService; import com.todoroo.astrid.service.AstridDependencyInjector; /** @@ -33,6 +34,7 @@ public class ReminderStartupReceiver extends BroadcastReceiver { ContextManager.setContext(context); try { ReminderService.getInstance().scheduleAllAlarms(); + AlarmService.getInstance().scheduleAllAlarms(); } catch (Exception e) { DependencyInjectionService.getInstance().inject(this); exceptionService.reportError("reminder-startup", e); //$NON-NLS-1$ diff --git a/astrid/res/values/strings-alarms.xml b/astrid/res/values/strings-alarms.xml index 17ab6e027..f6072d70b 100644 --- a/astrid/res/values/strings-alarms.xml +++ b/astrid/res/values/strings-alarms.xml @@ -11,6 +11,6 @@ Add an Alarm - Alarm! %s + Alarm! diff --git a/astrid/src/com/todoroo/astrid/dao/TaskDao.java b/astrid/src/com/todoroo/astrid/dao/TaskDao.java index 8716e1018..51e05543f 100644 --- a/astrid/src/com/todoroo/astrid/dao/TaskDao.java +++ b/astrid/src/com/todoroo/astrid/dao/TaskDao.java @@ -17,6 +17,7 @@ import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.sql.Criterion; import com.todoroo.andlib.sql.Functions; import com.todoroo.andlib.utility.DateUtilities; +import com.todoroo.astrid.alarms.AlarmService; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.model.Task; @@ -218,6 +219,7 @@ public class TaskDao extends GenericDao { afterComplete(task, values); else { ReminderService.getInstance().scheduleAlarm(task); + AlarmService.getInstance().scheduleAlarms(task); } Astrid2TaskProvider.notifyDatabaseModification();