diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index a6bb02e32..fe7ad6ace 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -479,9 +479,6 @@ - diff --git a/src/main/java/com/todoroo/astrid/dao/TaskDao.java b/src/main/java/com/todoroo/astrid/dao/TaskDao.java index 809fc7a6b..40a91fb82 100644 --- a/src/main/java/com/todoroo/astrid/dao/TaskDao.java +++ b/src/main/java/com/todoroo/astrid/dao/TaskDao.java @@ -9,6 +9,7 @@ import android.content.ContentValues; import android.database.sqlite.SQLiteConstraintException; import com.todoroo.andlib.data.AbstractModel; +import com.todoroo.andlib.data.Callback; import com.todoroo.andlib.data.DatabaseDao; import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.TodorooCursor; @@ -70,6 +71,10 @@ public class TaskDao { return dao.query(query); } + public void selectActive(Criterion criterion, Callback callback) { + dao.query(Query.select(Task.PROPERTIES).where(Criterion.and(TaskCriteria.isActive(), criterion)), callback); + } + public Task fetch(long id, Property... properties) { return dao.fetch(id, properties); } diff --git a/src/main/java/com/todoroo/astrid/data/Task.java b/src/main/java/com/todoroo/astrid/data/Task.java index 83d27fc2d..4c21c66bf 100644 --- a/src/main/java/com/todoroo/astrid/data/Task.java +++ b/src/main/java/com/todoroo/astrid/data/Task.java @@ -225,6 +225,10 @@ public class Task extends RemoteModel { return getValue(HIDE_UNTIL) > DateUtilities.now(); } + public boolean hasHideUntilDate() { + return getValue(HIDE_UNTIL) > 0; + } + /** Checks whether task is done. Requires DUE_DATE */ public boolean hasDueDate() { return getValue(DUE_DATE) > 0; diff --git a/src/main/java/org/tasks/Tasks.java b/src/main/java/org/tasks/Tasks.java index fd3748a62..57e8ec61d 100644 --- a/src/main/java/org/tasks/Tasks.java +++ b/src/main/java/org/tasks/Tasks.java @@ -23,7 +23,6 @@ import org.tasks.analytics.Tracker; import org.tasks.filters.FilterCounter; import org.tasks.injection.InjectingApplication; import org.tasks.preferences.Preferences; -import org.tasks.scheduling.RefreshScheduler; import org.tasks.sync.SyncThrottle; import javax.inject.Inject; @@ -51,7 +50,6 @@ public class Tasks extends InjectingApplication { @Inject TagService tagService; @Inject Broadcaster broadcaster; @Inject FilterCounter filterCounter; - @Inject RefreshScheduler refreshScheduler; @Inject SyncThrottle syncThrottle; @Inject Preferences preferences; @Inject Tracker tracker; diff --git a/src/main/java/org/tasks/injection/IntentServiceModule.java b/src/main/java/org/tasks/injection/IntentServiceModule.java index 10d906eba..b9067bc35 100644 --- a/src/main/java/org/tasks/injection/IntentServiceModule.java +++ b/src/main/java/org/tasks/injection/IntentServiceModule.java @@ -10,7 +10,6 @@ import dagger.Module; GeofenceSchedulingIntentService.class, BackupIntentService.class, GtasksBackgroundService.class, - MidnightRefreshService.class, RefreshSchedulerIntentService.class, ReminderSchedulerIntentService.class, GeofenceTransitionsIntentService.class, diff --git a/src/main/java/org/tasks/scheduling/BackgroundScheduler.java b/src/main/java/org/tasks/scheduling/BackgroundScheduler.java index 538b96208..d4ce1dbb8 100644 --- a/src/main/java/org/tasks/scheduling/BackgroundScheduler.java +++ b/src/main/java/org/tasks/scheduling/BackgroundScheduler.java @@ -17,7 +17,6 @@ public class BackgroundScheduler { } public void scheduleEverything() { - context.startService(new Intent(context, RefreshSchedulerIntentService.class)); context.startService(new Intent(context, GeofenceSchedulingIntentService.class)); context.startService(new Intent(context, ReminderSchedulerIntentService.class)); scheduleBackupService(); @@ -33,7 +32,7 @@ public class BackgroundScheduler { } public void scheduleMidnightRefresh() { - context.startService(new Intent(context, MidnightRefreshService.class)); + context.startService(new Intent(context, RefreshSchedulerIntentService.class)); } public void scheduleGtaskSync() { diff --git a/src/main/java/org/tasks/scheduling/BackupIntentService.java b/src/main/java/org/tasks/scheduling/BackupIntentService.java index 01dc7f97f..9bea02245 100644 --- a/src/main/java/org/tasks/scheduling/BackupIntentService.java +++ b/src/main/java/org/tasks/scheduling/BackupIntentService.java @@ -33,7 +33,7 @@ public class BackupIntentService extends MidnightIntentService { } @Override - String getLastRunPreference() { + protected String getLastRunPreference() { return TasksXmlExporter.PREF_BACKUP_LAST_DATE; } diff --git a/src/main/java/org/tasks/scheduling/MidnightIntentService.java b/src/main/java/org/tasks/scheduling/MidnightIntentService.java index 934308b2b..1ede849cc 100644 --- a/src/main/java/org/tasks/scheduling/MidnightIntentService.java +++ b/src/main/java/org/tasks/scheduling/MidnightIntentService.java @@ -10,9 +10,10 @@ import javax.inject.Inject; import timber.log.Timber; +import static com.google.common.base.Strings.isNullOrEmpty; import static java.util.concurrent.TimeUnit.SECONDS; import static org.tasks.time.DateTimeUtils.currentTimeMillis; -import static org.tasks.date.DateTimeUtils.newDateTime; +import static org.tasks.time.DateTimeUtils.nextMidnight; import static org.tasks.time.DateTimeUtils.printTimestamp; public abstract class MidnightIntentService extends InjectingIntentService { @@ -22,8 +23,11 @@ public abstract class MidnightIntentService extends InjectingIntentService { @Inject Preferences preferences; @Inject AlarmManager alarmManager; + private final String name; + public MidnightIntentService(String name) { super(name); + this.name = name; } @Override @@ -36,22 +40,22 @@ public abstract class MidnightIntentService extends InjectingIntentService { if (nextRun <= now) { nextRun = nextMidnight(now); - Timber.d("running now [nextRun=%s]", printTimestamp(nextRun)); - preferences.setLong(getLastRunPreference(), now); + Timber.d("%s running now [nextRun=%s]", name, printTimestamp(nextRun)); + if (!isNullOrEmpty(getLastRunPreference())) { + preferences.setLong(getLastRunPreference(), now); + } run(); } else { - Timber.d("will run at %s [lastRun=%s]", printTimestamp(nextRun), printTimestamp(lastRun)); + Timber.d("%s will run at %s [lastRun=%s]", name, printTimestamp(nextRun), printTimestamp(lastRun)); } PendingIntent pendingIntent = PendingIntent.getService(this, 0, new Intent(this, this.getClass()), PendingIntent.FLAG_UPDATE_CURRENT); alarmManager.noWakeup(nextRun + PADDING, pendingIntent); } - private static long nextMidnight(long timestamp) { - return newDateTime(timestamp).startOfDay().plusDays(1).getMillis(); - } - abstract void run(); - abstract String getLastRunPreference(); + protected String getLastRunPreference() { + return null; + } } diff --git a/src/main/java/org/tasks/scheduling/MidnightRefreshService.java b/src/main/java/org/tasks/scheduling/MidnightRefreshService.java deleted file mode 100644 index 242400a24..000000000 --- a/src/main/java/org/tasks/scheduling/MidnightRefreshService.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.tasks.scheduling; - -import org.tasks.Broadcaster; - -import javax.inject.Inject; - -public class MidnightRefreshService extends MidnightIntentService { - - @Inject Broadcaster broadcaster; - - public MidnightRefreshService() { - super(MidnightRefreshService.class.getSimpleName()); - } - - @Override - void run() { - broadcaster.refresh(); - } - - @Override - String getLastRunPreference() { - return "midnightRefreshDate"; - } -} diff --git a/src/main/java/org/tasks/scheduling/RefreshScheduler.java b/src/main/java/org/tasks/scheduling/RefreshScheduler.java index 55976d65c..8c60eda82 100644 --- a/src/main/java/org/tasks/scheduling/RefreshScheduler.java +++ b/src/main/java/org/tasks/scheduling/RefreshScheduler.java @@ -4,10 +4,8 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import com.todoroo.andlib.data.Property; -import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.andlib.data.Callback; import com.todoroo.andlib.sql.Criterion; -import com.todoroo.andlib.sql.Query; import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.data.Task; @@ -15,24 +13,21 @@ import org.tasks.injection.ForApplication; import org.tasks.receivers.RefreshReceiver; import javax.inject.Inject; -import javax.inject.Singleton; + +import timber.log.Timber; import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; import static com.todoroo.andlib.utility.DateUtilities.ONE_MINUTE; import static org.tasks.time.DateTimeUtils.currentTimeMillis; +import static org.tasks.time.DateTimeUtils.nextMidnight; +import static org.tasks.time.DateTimeUtils.printTimestamp; -@Singleton 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, - Task.HIDE_UNTIL - }; - @Inject public RefreshScheduler(TaskDao taskDao, @ForApplication Context context, AlarmManager alarmManager) { this.taskDao = taskDao; @@ -41,45 +36,39 @@ public class RefreshScheduler { } public void scheduleApplicationRefreshes() { - TodorooCursor cursor = getTasks(); - try { - for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { - Task task = new Task(cursor); + long now = currentTimeMillis(); + long midnight = nextMidnight(now); + Criterion criterion = Criterion.or( + Criterion.and(Task.HIDE_UNTIL.gt(now), Task.HIDE_UNTIL.lt(midnight)), + Criterion.and(Task.DUE_DATE.gt(now), Task.DUE_DATE.lt(midnight))); + taskDao.selectActive(criterion, new Callback() { + @Override + public void apply(Task task) { scheduleRefresh(task); } - } finally { - cursor.close(); - } + }); } public void scheduleRefresh(Task task) { - if (task.containsValue(Task.DUE_DATE)) { + if (task.isCompleted()) { + scheduleRefresh(task.getCompletionDate() + ONE_MINUTE); + } else if (task.hasDueDate()) { scheduleRefresh(task.getDueDate()); } - if (task.containsValue(Task.HIDE_UNTIL)) { + if (task.hasHideUntilDate()) { scheduleRefresh(task.getHideUntil()); } - if (task.containsValue(Task.COMPLETION_DATE)) { - scheduleRefresh(task.getCompletionDate() + ONE_MINUTE); - } - } - - private void scheduleRefresh(Long dueDate) { - if (currentTimeMillis() > dueDate) { - return; - } - - dueDate += 1000; // this is ghetto - Intent intent = new Intent(context, RefreshReceiver.class); - intent.setAction(Long.toString(dueDate)); - PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT); - alarmManager.noWakeup(dueDate, pendingIntent); } - private TodorooCursor getTasks() { + private void scheduleRefresh(Long refreshTime) { long now = currentTimeMillis(); - return taskDao.query(Query.select(REFRESH_PROPERTIES).where(Criterion.and( - TaskDao.TaskCriteria.isActive(), - Criterion.or(Task.HIDE_UNTIL.gt(now), Task.DUE_DATE.gt(now))))); + if (now < refreshTime && refreshTime < nextMidnight(now)) { + refreshTime += 1000; // this is ghetto + Timber.d("Scheduling refresh at %s", printTimestamp(refreshTime)); + Intent intent = new Intent(context, RefreshReceiver.class); + intent.setAction(Long.toString(refreshTime)); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT); + alarmManager.noWakeup(refreshTime, pendingIntent); + } } } diff --git a/src/main/java/org/tasks/scheduling/RefreshSchedulerIntentService.java b/src/main/java/org/tasks/scheduling/RefreshSchedulerIntentService.java index 9b46a02a1..4f82da2fe 100644 --- a/src/main/java/org/tasks/scheduling/RefreshSchedulerIntentService.java +++ b/src/main/java/org/tasks/scheduling/RefreshSchedulerIntentService.java @@ -1,15 +1,12 @@ package org.tasks.scheduling; -import android.content.Intent; - -import org.tasks.injection.InjectingIntentService; +import org.tasks.Broadcaster; import javax.inject.Inject; -import timber.log.Timber; - -public class RefreshSchedulerIntentService extends InjectingIntentService { +public class RefreshSchedulerIntentService extends MidnightIntentService { + @Inject Broadcaster broadcaster; @Inject RefreshScheduler refreshScheduler; public RefreshSchedulerIntentService() { @@ -17,11 +14,8 @@ public class RefreshSchedulerIntentService extends InjectingIntentService { } @Override - protected void onHandleIntent(Intent intent) { - super.onHandleIntent(intent); - - Timber.d("onHandleIntent(%s)", intent); - + void run() { refreshScheduler.scheduleApplicationRefreshes(); + broadcaster.refresh(); } } diff --git a/src/main/java/org/tasks/time/DateTimeUtils.java b/src/main/java/org/tasks/time/DateTimeUtils.java index d6477d578..bcf23bcb4 100644 --- a/src/main/java/org/tasks/time/DateTimeUtils.java +++ b/src/main/java/org/tasks/time/DateTimeUtils.java @@ -1,7 +1,11 @@ package org.tasks.time; +import org.tasks.BuildConfig; + import java.util.Date; +import static org.tasks.date.DateTimeUtils.newDateTime; + public class DateTimeUtils { private static final SystemMillisProvider SYSTEM_MILLIS_PROVIDER = new SystemMillisProvider(); @@ -19,7 +23,13 @@ public class DateTimeUtils { MILLIS_PROVIDER = SYSTEM_MILLIS_PROVIDER; } + public static long nextMidnight(long timestamp) { + return newDateTime(timestamp).startOfDay().plusDays(1).getMillis(); + } + public static String printTimestamp(long timestamp) { - return new Date(timestamp).toString(); + return BuildConfig.DEBUG + ? new Date(timestamp).toString() + : Long.toString(timestamp); } }