diff --git a/api/src/main/java/com/todoroo/astrid/data/TaskApiDao.java b/api/src/main/java/com/todoroo/astrid/data/TaskApiDao.java index 13f48bc5a..24776c026 100644 --- a/api/src/main/java/com/todoroo/astrid/data/TaskApiDao.java +++ b/api/src/main/java/com/todoroo/astrid/data/TaskApiDao.java @@ -27,7 +27,7 @@ public class TaskApiDao { /** @return tasks that are not hidden at current time */ public static Criterion isVisible() { - return Task.HIDE_UNTIL.lt(Functions.now()); + return Task.HIDE_UNTIL.lte(Functions.now()); } } diff --git a/astrid/src/main/AndroidManifest.xml b/astrid/src/main/AndroidManifest.xml index 1806c4226..35c15456d 100644 --- a/astrid/src/main/AndroidManifest.xml +++ b/astrid/src/main/AndroidManifest.xml @@ -201,6 +201,8 @@ + + diff --git a/astrid/src/main/java/com/todoroo/astrid/reminders/ReminderSchedulingService.java b/astrid/src/main/java/com/todoroo/astrid/reminders/ReminderSchedulingService.java index 331cdf157..bb13196c0 100644 --- a/astrid/src/main/java/com/todoroo/astrid/reminders/ReminderSchedulingService.java +++ b/astrid/src/main/java/com/todoroo/astrid/reminders/ReminderSchedulingService.java @@ -10,10 +10,14 @@ import android.content.Intent; import android.os.IBinder; import android.util.Log; +import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.ContextManager; +import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.astrid.alarms.AlarmService; +import org.tasks.scheduling.RefreshScheduler; + /** * Schedules reminders in the background to prevent ANR's * @@ -22,6 +26,13 @@ import com.todoroo.astrid.alarms.AlarmService; */ public class ReminderSchedulingService extends Service { + @Autowired + private RefreshScheduler refreshScheduler; + + public ReminderSchedulingService() { + DependencyInjectionService.getInstance().inject(this); + } + /** Receive the alarm - start the synchronize service! */ @Override public int onStartCommand(Intent intent, int flags, int startId) { @@ -32,7 +43,6 @@ public class ReminderSchedulingService extends Service { public void run() { delaySchedulingToPreventANRs(); scheduleReminders(); - stopSelf(); } }).start(); @@ -44,10 +54,13 @@ public class ReminderSchedulingService extends Service { try { ReminderService.getInstance().scheduleAllAlarms(); AlarmService.getInstance().scheduleAllAlarms(); + refreshScheduler.scheduleAllAlarms(); + } catch (Exception e) { Log.e("reminder-scheduling", "reminder-startup", e); } } + private void delaySchedulingToPreventANRs() { AndroidUtilities.sleepDeep(5000L); } @@ -56,5 +69,4 @@ public class ReminderSchedulingService extends Service { public IBinder onBind(Intent intent) { return null; } - } diff --git a/astrid/src/main/java/com/todoroo/astrid/service/AstridDependencyInjector.java b/astrid/src/main/java/com/todoroo/astrid/service/AstridDependencyInjector.java index 6fec335a2..b165b8177 100644 --- a/astrid/src/main/java/com/todoroo/astrid/service/AstridDependencyInjector.java +++ b/astrid/src/main/java/com/todoroo/astrid/service/AstridDependencyInjector.java @@ -28,6 +28,7 @@ import com.todoroo.astrid.utility.Constants; import org.tasks.Broadcaster; import org.tasks.filters.FilterCounter; +import org.tasks.scheduling.RefreshScheduler; /** * Astrid application dependency injector loads classes in Astrid with the @@ -88,6 +89,7 @@ public class AstridDependencyInjector extends AbstractDependencyInjector { injectables.put("broadcaster", Broadcaster.class); injectables.put("filterCounter", FilterCounter.class); + injectables.put("refreshScheduler", RefreshScheduler.class); // these make reference to fields defined above injectables.put("errorReporters", new ErrorReporter[] { diff --git a/astrid/src/main/java/com/todoroo/astrid/service/TaskService.java b/astrid/src/main/java/com/todoroo/astrid/service/TaskService.java index 505735755..19ab5dc86 100644 --- a/astrid/src/main/java/com/todoroo/astrid/service/TaskService.java +++ b/astrid/src/main/java/com/todoroo/astrid/service/TaskService.java @@ -41,6 +41,7 @@ import com.todoroo.astrid.utility.TitleParser; import org.tasks.Broadcaster; import org.tasks.filters.FilterCounter; +import org.tasks.scheduling.RefreshScheduler; import java.util.ArrayList; import java.util.List; @@ -82,6 +83,9 @@ public class TaskService { @Autowired private FilterCounter filterCounter; + @Autowired + private RefreshScheduler refreshScheduler; + public TaskService() { DependencyInjectionService.getInstance().inject(this); } @@ -121,6 +125,7 @@ public class TaskService { public void save(Task item) { taskDao.save(item); broadcastFilterListUpdated(); + refreshScheduler.scheduleRefresh(item); } private void saveWithoutPublishingFilterUpdate(Task item) { diff --git a/astrid/src/main/java/org/tasks/Broadcaster.java b/astrid/src/main/java/org/tasks/Broadcaster.java index 11c5e242d..a528c723e 100644 --- a/astrid/src/main/java/org/tasks/Broadcaster.java +++ b/astrid/src/main/java/org/tasks/Broadcaster.java @@ -9,8 +9,12 @@ public class Broadcaster { public void sendOrderedBroadcast(Intent intent) { Context context = ContextManager.getContext(); - if(context != null) { - context.sendOrderedBroadcast(intent, null); + if (context != null) { + sendOrderedBroadcast(context, intent); } } + + public void sendOrderedBroadcast(Context context, Intent intent) { + context.sendOrderedBroadcast(intent, null); + } } diff --git a/astrid/src/main/java/org/tasks/scheduling/RefreshScheduler.java b/astrid/src/main/java/org/tasks/scheduling/RefreshScheduler.java new file mode 100644 index 000000000..a21ef4cdd --- /dev/null +++ b/astrid/src/main/java/org/tasks/scheduling/RefreshScheduler.java @@ -0,0 +1,91 @@ +package org.tasks.scheduling; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import com.todoroo.andlib.data.Property; +import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.andlib.service.Autowired; +import com.todoroo.andlib.service.ContextManager; +import com.todoroo.andlib.service.DependencyInjectionService; +import com.todoroo.andlib.sql.Criterion; +import com.todoroo.andlib.sql.Query; +import com.todoroo.astrid.api.AstridApiConstants; +import com.todoroo.astrid.dao.TaskDao; +import com.todoroo.astrid.data.Task; + +import org.joda.time.DateTime; +import org.tasks.Broadcaster; + +import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; +import static org.tasks.date.DateTimeUtils.currentTimeMillis; + +public class RefreshScheduler extends BroadcastReceiver { + + private static final String TAG = "RefreshScheduler"; + + @Autowired + private TaskDao taskDao; + + @Autowired + private Broadcaster broadcaster; + + private static final Property[] REFRESH_PROPERTIES = new Property[]{ + Task.DUE_DATE, + Task.HIDE_UNTIL + }; + + public RefreshScheduler() { + DependencyInjectionService.getInstance().inject(this); + } + + @Override + public void onReceive(Context context, Intent intent) { + broadcaster.sendOrderedBroadcast(context, new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_LIST_UPDATED)); + broadcaster.sendOrderedBroadcast(context, new Intent(AstridApiConstants.BROADCAST_EVENT_FILTER_LIST_UPDATED)); + } + + public void scheduleAllAlarms() { + TodorooCursor cursor = getTasks(); + try { + Task task = new Task(); + for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { + task.readFromCursor(cursor); + scheduleRefresh(task); + } + } finally { + cursor.close(); + } + } + + public void scheduleRefresh(Task task) { + if (task.containsValue(Task.DUE_DATE)) { + scheduleRefresh(task.getDueDate()); + } + if (task.containsValue(Task.HIDE_UNTIL)) { + scheduleRefresh(task.getHideUntil()); + } + } + + private void scheduleRefresh(Long dueDate) { + dueDate += 1000; // this is ghetto + Context context = ContextManager.getContext(); + Intent intent = new Intent(context, RefreshScheduler.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); + } + + private TodorooCursor getTasks() { + long now = currentTimeMillis(); + return taskDao.query(Query.select(REFRESH_PROPERTIES).where(Criterion.and( + TaskDao.TaskCriteria.isActive(), + TaskDao.TaskCriteria.ownedByMe(), + Criterion.or(Task.HIDE_UNTIL.gt(now), Task.DUE_DATE.gt(now))))); + } +}