/** * Schedules alarms for a single task * * @param shouldPerformPropertyCheck whether to check if task has requisite properties */ private void scheduleAlarm(Task task, boolean shouldPerformPropertyCheck) { if (task == null || !task.isSaved()) return; // read data if necessary if (shouldPerformPropertyCheck) { for (Property<?> property : NOTIFICATION_PROPERTIES) { if (!task.containsValue(property)) { task = taskDao.fetch(task.getId(), NOTIFICATION_PROPERTIES); if (task == null) return; break; } } } // Make sure no alarms are scheduled other than the next one. When that one is shown, it // will schedule the next one after it, and so on and so forth. clearAllAlarms(task); if (task.isCompleted() || task.isDeleted() || !Task.USER_ID_SELF.equals(task.getValue(Task.USER_ID))) { return; } // snooze reminder long whenSnooze = calculateNextSnoozeReminder(task); // random reminders long whenRandom = calculateNextRandomReminder(task); // notifications at due date long whenDueDate = calculateNextDueDateReminder(task); // notifications after due date long whenOverdue = calculateNextOverdueReminder(task); // For alarms around/before now, increment the now value so the next one will be later if (whenDueDate <= now || whenOverdue <= now) { whenDueDate = now; whenOverdue = now; now += 30 * DateUtilities.ONE_MINUTE; // Prevents overdue tasks from being scheduled all at once } // if random reminders are too close to due date, favor due date if (whenRandom != NO_ALARM && whenDueDate - whenRandom < DateUtilities.ONE_DAY) whenRandom = NO_ALARM; // snooze trumps all if (whenSnooze != NO_ALARM) { scheduler.createAlarm(task, whenSnooze, TYPE_SNOOZE); } else if (whenRandom < whenDueDate && whenRandom < whenOverdue) { scheduler.createAlarm(task, whenRandom, TYPE_RANDOM); } else if (whenDueDate < whenOverdue) { scheduler.createAlarm(task, whenDueDate, TYPE_DUE); } else if (whenOverdue != NO_ALARM) { scheduler.createAlarm(task, whenOverdue, TYPE_OVERDUE); } else { scheduler.createAlarm(task, 0, 0); } }
/** * Show a new notification about the given task. Returns false if there was some sort of error or * the alarm should be disabled. */ public boolean showTaskNotification(long id, int type, String reminder) { Task task; try { task = taskDao.fetch( id, Task.ID, Task.TITLE, Task.HIDE_UNTIL, Task.COMPLETION_DATE, Task.DUE_DATE, Task.DELETION_DATE, Task.REMINDER_FLAGS); if (task == null) throw new IllegalArgumentException("cound not find item with id"); // $NON-NLS-1$ } catch (Exception e) { exceptionService.reportError("show-notif", e); // $NON-NLS-1$ return false; } // you're done - don't sound, do delete if (task.isCompleted() || task.isDeleted()) return false; // it's hidden - don't sound, don't delete if (task.isHidden() && type == ReminderService.TYPE_RANDOM) return true; // task due date was changed, but alarm wasn't rescheduled if ((type == ReminderService.TYPE_DUE || type == ReminderService.TYPE_OVERDUE) && (!task.hasDueDate() || task.getValue(Task.DUE_DATE) > DateUtilities.now())) return true; // read properties String taskTitle = task.getValue(Task.TITLE); boolean nonstopMode = task.getFlag(Task.REMINDER_FLAGS, Task.NOTIFY_MODE_NONSTOP); boolean ringFiveMode = task.getFlag(Task.REMINDER_FLAGS, Task.NOTIFY_MODE_FIVE); int ringTimes = nonstopMode ? -1 : (ringFiveMode ? 5 : 1); // update last reminder time task.setValue(Task.REMINDER_LAST, DateUtilities.now()); taskDao.saveExisting(task); Context context = ContextManager.getContext(); String title = context.getString(R.string.app_name); String text = reminder + " " + taskTitle; // $NON-NLS-1$ Intent notifyIntent = new Intent(context, NotificationActivity.class); notifyIntent.setAction("NOTIFY" + id); // $NON-NLS-1$ notifyIntent.putExtra(NotificationActivity.TOKEN_ID, id); notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); showNotification((int) id, notifyIntent, type, title, text, ringTimes); return true; }