From 4d46900f4549a2951b866ccf35140efc4e8581d7 Mon Sep 17 00:00:00 2001 From: Tim Su Date: Sat, 27 Dec 2008 10:35:41 +0000 Subject: [PATCH] Got the alarm stuff working... I think. --- AndroidManifest.xml | 2 +- res/drawable/strikeout.png | Bin 144 -> 176 bytes res/layout/task_edit.xml | 6 +- res/values/strings.xml | 7 ++ src/com/timsu/astrid/activities/TagList.java | 21 ++++ src/com/timsu/astrid/activities/TaskEdit.java | 16 ++- src/com/timsu/astrid/activities/TaskList.java | 28 +++--- src/com/timsu/astrid/activities/TaskView.java | 9 +- .../astrid/data/task/TaskController.java | 2 + .../astrid/data/task/TaskModelForNotify.java | 8 ++ .../astrid/data/task/TaskModelForView.java | 6 ++ .../timsu/astrid/utilities/Notifications.java | 91 ++++++++++++------ .../astrid/utilities/StartupReceiver.java | 14 +++ .../astrid/widget/NNumberPickerDialog.java | 4 +- 14 files changed, 154 insertions(+), 60 deletions(-) create mode 100644 src/com/timsu/astrid/utilities/StartupReceiver.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 636de0c65..ab31b1bd9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -23,7 +23,7 @@ - + diff --git a/res/drawable/strikeout.png b/res/drawable/strikeout.png index b9f86709da05454089570f8564cd786c1244a5e0..608cb239ee7c2030aa8c523a06ccfc263b538a44 100644 GIT binary patch delta 113 zcmbQhxPftkIF~2~8v_G_`q?+HCMt??{$~Kf1$&oIp6HhoJZptOOfi(`n# z@wb-(IS()h9KIl8_J5MGtP4dZJ$b*ZO7a7P{)Wx03|A&M - - + --> diff --git a/res/values/strings.xml b/res/values/strings.xml index 1998a2262..f176a0ea6 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -141,10 +141,15 @@ Create Task With Tag Edit Tag Delete Tag + + Sort A-Z + Sort by Size Question + Yes + No Delete Delete this task? @@ -152,5 +157,7 @@ Stop the timer? + Next notification time: + diff --git a/src/com/timsu/astrid/activities/TagList.java b/src/com/timsu/astrid/activities/TagList.java index 303fac53b..8a37d5f63 100644 --- a/src/com/timsu/astrid/activities/TagList.java +++ b/src/com/timsu/astrid/activities/TagList.java @@ -58,6 +58,8 @@ public class TagList extends Activity { private static final int ACTIVITY_LIST = 0; private static final int ACTIVITY_CREATE = 1; + private static final int MENU_SORT_ALPHA_ID = Menu.FIRST; + private static final int MENU_SORT_SIZE_ID = Menu.FIRST + 1; private static final int CONTEXT_CREATE_ID = Menu.FIRST + 10; private static final int CONTEXT_DELETE_ID = Menu.FIRST + 11; @@ -228,4 +230,23 @@ public class TagList extends Activity { super.onDestroy(); controller.close(); } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + + MenuItem item; + + item = menu.add(Menu.NONE, MENU_SORT_ALPHA_ID, Menu.NONE, + R.string.tagList_menu_sortAlpha); + item.setIcon(android.R.drawable.ic_menu_sort_alphabetically); + item.setAlphabeticShortcut('a'); + + item = menu.add(Menu.NONE, MENU_SORT_SIZE_ID, Menu.NONE, + R.string.tagList_menu_sortSize); + item.setIcon(android.R.drawable.ic_menu_sort_by_size); + item.setAlphabeticShortcut('s'); + + return true; + } } \ No newline at end of file diff --git a/src/com/timsu/astrid/activities/TaskEdit.java b/src/com/timsu/astrid/activities/TaskEdit.java index 1ea86fbb8..b87c419ea 100644 --- a/src/com/timsu/astrid/activities/TaskEdit.java +++ b/src/com/timsu/astrid/activities/TaskEdit.java @@ -77,7 +77,7 @@ public class TaskEdit extends TaskModificationActivity { private static final int DELETE_ID = Menu.FIRST + 2; // activity results - public static final int RESULT_DELETE = RESULT_FIRST_USER; + public static final int RESULT_DELETE = RESULT_FIRST_USER + 10; // other constants private static final int MAX_TAGS = 5; @@ -146,7 +146,7 @@ public class TaskEdit extends TaskModificationActivity { definiteDueDate.setDate(model.getDefiniteDueDate()); preferredDueDate.setDate(model.getPreferredDueDate()); hiddenUntil.setDate(model.getHiddenUntil()); - blockingOn.setBlockingOn(model.getBlockingOn()); + // blockingOn.setBlockingOn(model.getBlockingOn()); notification.setTimeDuration(model.getNotificationIntervalSeconds()); notes.setText(model.getNotes()); @@ -186,7 +186,7 @@ public class TaskEdit extends TaskModificationActivity { model.setDefiniteDueDate(definiteDueDate.getDate()); model.setPreferredDueDate(preferredDueDate.getDate()); model.setHiddenUntil(hiddenUntil.getDate()); - model.setBlockingOn(blockingOn.getBlockingOn()); + // model.setBlockingOn(blockingOn.getBlockingOn()); model.setNotes(notes.getText().toString()); model.setNotificationIntervalSeconds(notification.getTimeDurationInSeconds()); @@ -198,10 +198,8 @@ public class TaskEdit extends TaskModificationActivity { Log.e(getClass().getSimpleName(), "Error saving task!", e); // TODO } - // recompute task visibility - // set up notification - Notifications.scheduleNextNotification(this, model); + Notifications.scheduleNextAlarm(this, model); } /** Save task tags. Must be called after task already has an ID */ @@ -264,7 +262,7 @@ public class TaskEdit extends TaskModificationActivity { TimeDurationType.HOURS_MINUTES); notification = new TimeDurationControlSet(this, R.id.notification, R.string.notification_prefix, R.string.notification_dialog, - TimeDurationType.DAYS_HOURS); + TimeDurationType.HOURS_MINUTES); definiteDueDate = new DateControlSet(this, R.id.definiteDueDate_notnull, R.id.definiteDueDate_date, R.id.definiteDueDate_time); preferredDueDate = new DateControlSet(this, R.id.preferredDueDate_notnull, @@ -272,8 +270,8 @@ public class TaskEdit extends TaskModificationActivity { hiddenUntil = new DateControlSet(this, R.id.hiddenUntil_notnull, R.id.hiddenUntil_date, R.id.hiddenUntil_time); notes = (EditText)findViewById(R.id.notes); - blockingOn = new BlockingOnControlSet(R.id.blockingOn_notnull, - R.id.blockingon); +// blockingOn = new BlockingOnControlSet(R.id.blockingOn_notnull, +// R.id.blockingon); // individual ui component initialization ImportanceAdapter importanceAdapter = new ImportanceAdapter(this, diff --git a/src/com/timsu/astrid/activities/TaskList.java b/src/com/timsu/astrid/activities/TaskList.java index 1cc4fa0da..b0d53f270 100644 --- a/src/com/timsu/astrid/activities/TaskList.java +++ b/src/com/timsu/astrid/activities/TaskList.java @@ -59,20 +59,20 @@ import com.timsu.astrid.data.task.TaskModelForList; public class TaskList extends Activity { // bundle tokens - public static final String TAG_TOKEN = "tag"; + public static final String TAG_TOKEN = "tag"; // activities - private static final int ACTIVITY_CREATE = 0; - private static final int ACTIVITY_VIEW = 1; - private static final int ACTIVITY_EDIT = 2; - private static final int ACTIVITY_TAGS = 3; + private static final int ACTIVITY_CREATE = 0; + private static final int ACTIVITY_VIEW = 1; + private static final int ACTIVITY_EDIT = 2; + private static final int ACTIVITY_TAGS = 3; // menu codes - private static final int INSERT_ID = Menu.FIRST; - private static final int FILTERS_ID = Menu.FIRST + 1; - private static final int TAGS_ID = Menu.FIRST + 2; - private static final int CONTEXT_FILTER_HIDDEN = Menu.FIRST + 20; - private static final int CONTEXT_FILTER_DONE = Menu.FIRST + 21; + private static final int INSERT_ID = Menu.FIRST; + private static final int FILTERS_ID = Menu.FIRST + 1; + private static final int TAGS_ID = Menu.FIRST + 2; + private static final int CONTEXT_FILTER_HIDDEN = Menu.FIRST + 20; + private static final int CONTEXT_FILTER_DONE = Menu.FIRST + 21; // UI components private TaskController controller; @@ -175,7 +175,7 @@ public class TaskList extends Activity { title.append(r.getQuantityString(R.plurals.Ntasks, taskArray.size(), taskArray.size())); if(hiddenTasks > 0) - title.append(" (").append(hiddenTasks).append(" "). + title.append(" (+").append(hiddenTasks).append(" "). append(r.getString(R.string.taskList_hiddenSuffix)).append(")"); setTitle(title); @@ -228,6 +228,12 @@ public class TaskList extends Activity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { + + if(resultCode == TaskView.RESULT_DISMISS) { + finish(); + return; + } + fillData(); } diff --git a/src/com/timsu/astrid/activities/TaskView.java b/src/com/timsu/astrid/activities/TaskView.java index f09310565..90105dc16 100644 --- a/src/com/timsu/astrid/activities/TaskView.java +++ b/src/com/timsu/astrid/activities/TaskView.java @@ -61,6 +61,9 @@ public class TaskView extends TaskModificationActivity { private static final int EDIT_ID = Menu.FIRST; private static final int DELETE_ID = Menu.FIRST + 1; + // activity results + public static final int RESULT_DISMISS = RESULT_FIRST_USER + 20; + // UI components private TextView name; private TextView elapsed; @@ -105,7 +108,7 @@ public class TaskView extends TaskModificationActivity { // clear residual, schedule the next one Notifications.clearAllNotifications(this, model.getTaskIdentifier()); - Notifications.scheduleNextNotification(this, model); + Notifications.scheduleNextAlarm(this, model); String[] responses = r.getStringArray(R.array.reminder_responses); String response = responses[new Random().nextInt(responses.length)]; @@ -113,8 +116,8 @@ public class TaskView extends TaskModificationActivity { .setTitle(R.string.taskView_notifyTitle) .setMessage(response) .setIcon(android.R.drawable.ic_dialog_alert) - .setPositiveButton(android.R.string.yes, null) - .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { + .setPositiveButton(R.string.yes, null) + .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { setResult(RESULT_CANCELED); diff --git a/src/com/timsu/astrid/data/task/TaskController.java b/src/com/timsu/astrid/data/task/TaskController.java index 754c8c897..092844aad 100644 --- a/src/com/timsu/astrid/data/task/TaskController.java +++ b/src/com/timsu/astrid/data/task/TaskController.java @@ -31,6 +31,7 @@ import android.database.sqlite.SQLiteOpenHelper; import com.timsu.astrid.data.AbstractController; import com.timsu.astrid.data.task.AbstractTaskModel.TaskModelDatabaseHelper; +import com.timsu.astrid.utilities.Notifications; /** Controller for task-related operations */ public class TaskController extends AbstractController { @@ -118,6 +119,7 @@ public class TaskController extends AbstractController { if(taskId == null) throw new UnsupportedOperationException("Cannot delete uncreated task!"); long id = taskId.getId(); + Notifications.deleteAlarm(context, id); return database.delete(TASK_TABLE_NAME, KEY_ROWID + "=" + id, null) > 0; } diff --git a/src/com/timsu/astrid/data/task/TaskModelForNotify.java b/src/com/timsu/astrid/data/task/TaskModelForNotify.java index 87b68e260..652ba165e 100644 --- a/src/com/timsu/astrid/data/task/TaskModelForNotify.java +++ b/src/com/timsu/astrid/data/task/TaskModelForNotify.java @@ -19,6 +19,8 @@ */ package com.timsu.astrid.data.task; +import java.util.Date; + import android.database.Cursor; import com.timsu.astrid.data.AbstractController; @@ -32,6 +34,7 @@ public class TaskModelForNotify extends AbstractTaskModel implements Notifiable static String[] FIELD_LIST = new String[] { AbstractController.KEY_ROWID, NOTIFICATIONS, + HIDDEN_UNTIL, }; // --- constructors @@ -39,6 +42,7 @@ public class TaskModelForNotify extends AbstractTaskModel implements Notifiable public TaskModelForNotify(Cursor cursor) { super(cursor); getNotificationIntervalSeconds(); + getHiddenUntil(); } // --- getters and setters @@ -48,4 +52,8 @@ public class TaskModelForNotify extends AbstractTaskModel implements Notifiable return super.getNotificationIntervalSeconds(); } + @Override + public Date getHiddenUntil() { + return super.getHiddenUntil(); + } } diff --git a/src/com/timsu/astrid/data/task/TaskModelForView.java b/src/com/timsu/astrid/data/task/TaskModelForView.java index 35e2cc3c9..ef2ed402c 100644 --- a/src/com/timsu/astrid/data/task/TaskModelForView.java +++ b/src/com/timsu/astrid/data/task/TaskModelForView.java @@ -42,6 +42,7 @@ public class TaskModelForView extends AbstractTaskModel implements Notifiable { TIMER_START, DEFINITE_DUE_DATE, PREFERRED_DUE_DATE, + HIDDEN_UNTIL, CREATION_DATE, NOTIFICATIONS, NOTES, @@ -120,6 +121,11 @@ public class TaskModelForView extends AbstractTaskModel implements Notifiable { return super.getCreationDate(); } + @Override + public Date getHiddenUntil() { + return super.getHiddenUntil(); + } + @Override public void setTimerStart(Date timerStart) { super.setTimerStart(timerStart); diff --git a/src/com/timsu/astrid/utilities/Notifications.java b/src/com/timsu/astrid/utilities/Notifications.java index 507ac7845..64e51fc62 100644 --- a/src/com/timsu/astrid/utilities/Notifications.java +++ b/src/com/timsu/astrid/utilities/Notifications.java @@ -1,9 +1,11 @@ package com.timsu.astrid.utilities; +import java.util.Date; import java.util.List; import java.util.Random; import android.app.Activity; +import android.app.AlarmManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -21,53 +23,82 @@ import com.timsu.astrid.data.task.TaskModelForNotify; public class Notifications extends BroadcastReceiver { - private static final int MIN_INTERVAL_SECONDS = 60; + private static final String ID_KEY = "id"; + private static final int MIN_INTERVAL_SECONDS = 120; private static Random random = new Random(); + /** Something we can create a notification for */ + public interface Notifiable { + public TaskIdentifier getTaskIdentifier(); + public Integer getNotificationIntervalSeconds(); + public Date getHiddenUntil(); + } + @Override /** Startup intent */ public void onReceive(Context context, Intent intent) { - NotificationManager nm = (NotificationManager) context. - getSystemService(Context.NOTIFICATION_SERVICE); - - Notification notification = new Notification( - android.R.drawable.stat_notify_chat, "started up", - System.currentTimeMillis()); + long id = intent.getLongExtra(ID_KEY, 0); + Log.e("ALARM", "Alarm triggered id " + id); + showNotification(context, id); + } - nm.notify(0, notification); + // --- alarm manager stuff + public static void scheduleAllAlarms(Context context) { TaskController controller = new TaskController(context); controller.open(); List tasks = controller.getTasksWithNotifications(); for(TaskModelForNotify task : tasks) - scheduleNextNotification(context, task); - } - - public interface Notifiable { - public TaskIdentifier getTaskIdentifier(); - public Integer getNotificationIntervalSeconds(); + scheduleNextAlarm(context, task); } /** Schedules the next notification for this task */ - public static void scheduleNextNotification(Context context, + public static void scheduleNextAlarm(Context context, Notifiable task) { if(task.getNotificationIntervalSeconds() == null || task.getNotificationIntervalSeconds() == 0 || task.getTaskIdentifier() == null) return; - // TODO if task is hidden, disregard + if(task.getHiddenUntil() != null && task.getHiddenUntil().after(new Date())) + return; + + // compute, and add a fudge factor to mix things up a bit + int interval = task.getNotificationIntervalSeconds(); + int currentSeconds = (int)(System.currentTimeMillis() / 1000); + int untilNextInterval = interval - currentSeconds % interval; + untilNextInterval *= 0.2f + random.nextFloat() * 0.6f; + if(untilNextInterval < MIN_INTERVAL_SECONDS) + untilNextInterval = MIN_INTERVAL_SECONDS; + long when = System.currentTimeMillis() + untilNextInterval * 1000; + scheduleAlarm(context, task.getTaskIdentifier().getId(), when); + } + + /** Delete the given alarm */ + public static void deleteAlarm(Context context, long id) { + AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); - // add a fudge factor to mix things up a bit - int nextSeconds = (int)((random.nextFloat() * 0.2f + 0.8f) * - task.getNotificationIntervalSeconds()/60); // TODO remove /60 - if(nextSeconds < MIN_INTERVAL_SECONDS) - nextSeconds = MIN_INTERVAL_SECONDS; - long when = System.currentTimeMillis() + nextSeconds * 1000; - scheduleNotification(context, task.getTaskIdentifier(), when); + Intent intent = new Intent(context, Notifications.class); + intent.putExtra(ID_KEY, id); + PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0); + + am.cancel(sender); + } + + /** Schedules a single alarm */ + public static void scheduleAlarm(Context context, long id, long when) { + AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); + + Intent intent = new Intent(context, Notifications.class); + intent.putExtra(ID_KEY, id); + PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0); + + Log.e("ALARM", "Alarm set for " + new Date(when)); + am.set(AlarmManager.RTC, when, sender); } + // --- notification manager stuff /** Clear notifications associated with this application */ public static void clearAllNotifications(Context context, TaskIdentifier taskId) { @@ -77,16 +108,14 @@ public class Notifications extends BroadcastReceiver { } /** Schedule a new notification about the given task */ - public static void scheduleNotification(Context context, - TaskIdentifier taskId, long when) { + public static void showNotification(Context context, long id) { NotificationManager nm = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); Resources r = context.getResources(); Intent notifyIntent = new Intent(context, TaskView.class); - notifyIntent.putExtra(TaskView.LOAD_INSTANCE_TOKEN, - taskId.getId()); + notifyIntent.putExtra(TaskView.LOAD_INSTANCE_TOKEN, id); notifyIntent.putExtra(TaskView.FROM_NOTIFICATION_TOKEN, true); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notifyIntent, PendingIntent.FLAG_ONE_SHOT); @@ -98,7 +127,8 @@ public class Notifications extends BroadcastReceiver { String reminder = reminders[next]; Notification notification = new Notification( - android.R.drawable.stat_notify_chat, reminder, when); + android.R.drawable.stat_notify_chat, reminder, + System.currentTimeMillis()); notification.setLatestEventInfo(context, appName, @@ -109,9 +139,8 @@ public class Notifications extends BroadcastReceiver { notification.vibrate = new long[] { 300, 50, 50, 300, 100, 300, 100, 100, 200 }; - Log.w("Notifications", "Logging notification: " + reminder + " for " + - (when - System.currentTimeMillis())/1000 + " seconds from now"); - nm.notify((int)taskId.getId(), notification); + Log.w("Notifications", "Logging notification: " + reminder); + nm.notify((int)id, notification); } } \ No newline at end of file diff --git a/src/com/timsu/astrid/utilities/StartupReceiver.java b/src/com/timsu/astrid/utilities/StartupReceiver.java new file mode 100644 index 000000000..3cef41138 --- /dev/null +++ b/src/com/timsu/astrid/utilities/StartupReceiver.java @@ -0,0 +1,14 @@ +package com.timsu.astrid.utilities; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class StartupReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + // do nothing...? + } + +} diff --git a/src/com/timsu/astrid/widget/NNumberPickerDialog.java b/src/com/timsu/astrid/widget/NNumberPickerDialog.java index 014cb4ee5..632f25370 100644 --- a/src/com/timsu/astrid/widget/NNumberPickerDialog.java +++ b/src/com/timsu/astrid/widget/NNumberPickerDialog.java @@ -94,8 +94,8 @@ public class NNumberPickerDialog extends AlertDialog implements OnClickListener if(separators[i].length() < 3) text.setTextSize(48); else - text.setTextSize(24); - text.setGravity(Gravity.CENTER_VERTICAL); + text.setTextSize(20); + text.setGravity(Gravity.CENTER); text.setLayoutParams(sepLayout); container.addView(text); }