Replace android-job with intent services

pull/511/merge
Alex Baker 9 years ago
parent 244ac6c9e6
commit ac03c211e0

@ -134,7 +134,6 @@ dependencies {
compile 'com.google.android.apps.dashclock:dashclock-api:2.0.0' compile 'com.google.android.apps.dashclock:dashclock-api:2.0.0'
compile 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2' compile 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2'
compile 'com.bignerdranch.android:recyclerview-multiselect:0.2' compile 'com.bignerdranch.android:recyclerview-multiselect:0.2'
compile 'com.evernote:android-job:1.1.8'
compile ('com.rubiconproject.oss:jchronic:0.2.6') { compile ('com.rubiconproject.oss:jchronic:0.2.6') {
transitive = false transitive = false
} }

10
proguard.pro vendored

@ -37,13 +37,3 @@
# https://github.com/facebook/stetho/blob/2807d4248c6fa06cdd3626b6afb9bfc42ba50d55/stetho/proguard-consumer.pro # https://github.com/facebook/stetho/blob/2807d4248c6fa06cdd3626b6afb9bfc42ba50d55/stetho/proguard-consumer.pro
-keep class com.facebook.stetho.** { *; } -keep class com.facebook.stetho.** { *; }
-dontwarn com.facebook.stetho.** -dontwarn com.facebook.stetho.**
# https://github.com/evernote/android-job/blob/7f81ac43d0b161f4f0bed1e02c2455a3cda57041/library/proguard.txt
-dontwarn com.evernote.android.job.gcm.**
-dontwarn com.evernote.android.job.util.GcmAvailableHelper
-keep public class com.evernote.android.job.v21.PlatformJobService
-keep public class com.evernote.android.job.v14.PlatformAlarmService
-keep public class com.evernote.android.job.v14.PlatformAlarmReceiver
-keep public class com.evernote.android.job.JobBootReceiver
-keep public class com.evernote.android.job.JobRescheduleService

@ -19,6 +19,7 @@ import org.junit.runner.RunWith;
import org.tasks.R; import org.tasks.R;
import org.tasks.injection.TestComponent; import org.tasks.injection.TestComponent;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.scheduling.AlarmManager;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -29,6 +30,7 @@ import static android.support.test.InstrumentationRegistry.getTargetContext;
import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.tasks.date.DateTimeUtils.newDateTime; import static org.tasks.date.DateTimeUtils.newDateTime;
import static org.tasks.time.DateTimeUtils.currentTimeMillis; import static org.tasks.time.DateTimeUtils.currentTimeMillis;
@ -90,7 +92,7 @@ public class BackupServiceTests extends DatabaseTestCase {
preferences.setLong(TasksXmlExporter.PREF_BACKUP_LAST_DATE, 0); preferences.setLong(TasksXmlExporter.PREF_BACKUP_LAST_DATE, 0);
// create a backup // create a backup
BackupJob service = new BackupJob(getTargetContext(), new JobManager(getTargetContext()), xmlExporter, preferences); BackupJob service = new BackupJob(getTargetContext(), new JobManager(getTargetContext(), mock(AlarmManager.class)), xmlExporter, preferences);
service.startBackup(getTargetContext()); service.startBackup(getTargetContext());
AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME); AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME);
@ -128,7 +130,7 @@ public class BackupServiceTests extends DatabaseTestCase {
assertEquals(11, files.length); assertEquals(11, files.length);
// backup // backup
BackupJob service = new BackupJob(getTargetContext(), new JobManager(getTargetContext()), xmlExporter, preferences); BackupJob service = new BackupJob(getTargetContext(), new JobManager(getTargetContext(), mock(AlarmManager.class)), xmlExporter, preferences);
service.startBackup(getTargetContext()); service.startBackup(getTargetContext());
AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME); AndroidUtilities.sleepDeep(BACKUP_WAIT_TIME);

@ -53,7 +53,7 @@ public class JobQueueTest {
queue.add(new Reminder(1, 1, 0)); queue.add(new Reminder(1, 1, 0));
queue.add(new Reminder(2, 1, 0)); queue.add(new Reminder(2, 1, 0));
verify(jobManager).schedule(TAG, 1, true); verify(jobManager).schedule(TAG, 1);
assertEquals(2, queue.size()); assertEquals(2, queue.size());
} }
@ -62,7 +62,7 @@ public class JobQueueTest {
public void rescheduleForFirstJob() { public void rescheduleForFirstJob() {
queue.add(new Reminder(1, 1, 0)); queue.add(new Reminder(1, 1, 0));
verify(jobManager).schedule(TAG, 1, true); verify(jobManager).schedule(TAG, 1);
} }
@Test @Test
@ -70,7 +70,7 @@ public class JobQueueTest {
queue.add(new Reminder(1, 1, 0)); queue.add(new Reminder(1, 1, 0));
queue.add(new Reminder(2, 2, 0)); queue.add(new Reminder(2, 2, 0));
verify(jobManager).schedule(TAG, 1, true); verify(jobManager).schedule(TAG, 1);
} }
@Test @Test
@ -79,8 +79,8 @@ public class JobQueueTest {
queue.add(new Reminder(1, 1, 0)); queue.add(new Reminder(1, 1, 0));
InOrder order = inOrder(jobManager); InOrder order = inOrder(jobManager);
order.verify(jobManager).schedule(TAG, 2, true); order.verify(jobManager).schedule(TAG, 2);
order.verify(jobManager).schedule(TAG, 1, true); order.verify(jobManager).schedule(TAG, 1);
} }
@Test @Test
@ -89,7 +89,7 @@ public class JobQueueTest {
queue.cancel(1); queue.cancel(1);
InOrder order = inOrder(jobManager); InOrder order = inOrder(jobManager);
order.verify(jobManager).schedule(TAG, 2, true); order.verify(jobManager).schedule(TAG, 2);
order.verify(jobManager).cancel(TAG); order.verify(jobManager).cancel(TAG);
} }
@ -101,8 +101,8 @@ public class JobQueueTest {
queue.cancel(1); queue.cancel(1);
InOrder order = inOrder(jobManager); InOrder order = inOrder(jobManager);
order.verify(jobManager).schedule(TAG, 1, true); order.verify(jobManager).schedule(TAG, 1);
order.verify(jobManager).schedule(TAG, 2, true); order.verify(jobManager).schedule(TAG, 2);
} }
@Test @Test
@ -112,7 +112,7 @@ public class JobQueueTest {
queue.cancel(2); queue.cancel(2);
verify(jobManager).schedule(TAG, 1, true); verify(jobManager).schedule(TAG, 1);
} }
@Test @Test
@ -127,7 +127,7 @@ public class JobQueueTest {
when(preferences.adjustForQuietHours(anyLong())).thenReturn(1234L); when(preferences.adjustForQuietHours(anyLong())).thenReturn(1234L);
queue.add(new Reminder(1, 1, 1)); queue.add(new Reminder(1, 1, 1));
verify(jobManager).schedule(TAG, 1234, true); verify(jobManager).schedule(TAG, 1234);
} }
@Test @Test
@ -137,7 +137,7 @@ public class JobQueueTest {
queue.add(new Reminder(1, now, TYPE_DUE)); queue.add(new Reminder(1, now, TYPE_DUE));
queue.add(new Reminder(2, now + ONE_MINUTE, TYPE_DUE)); queue.add(new Reminder(2, now + ONE_MINUTE, TYPE_DUE));
verify(jobManager).schedule(TAG, now, true); verify(jobManager).schedule(TAG, now);
Freeze.freezeAt(now).thawAfter(new Snippet() {{ Freeze.freezeAt(now).thawAfter(new Snippet() {{
assertEquals( assertEquals(
@ -153,7 +153,7 @@ public class JobQueueTest {
queue.add(new Reminder(1, now, TYPE_DUE)); queue.add(new Reminder(1, now, TYPE_DUE));
queue.add(new Reminder(2, now + ONE_MINUTE, TYPE_DUE)); queue.add(new Reminder(2, now + ONE_MINUTE, TYPE_DUE));
verify(jobManager).schedule(TAG, now, true); verify(jobManager).schedule(TAG, now);
Freeze.freezeAt(now).thawAfter(new Snippet() {{ Freeze.freezeAt(now).thawAfter(new Snippet() {{
queue.removeOverdueJobs(); queue.removeOverdueJobs();
@ -171,7 +171,7 @@ public class JobQueueTest {
queue.clear(); queue.clear();
InOrder order = inOrder(jobManager); InOrder order = inOrder(jobManager);
order.verify(jobManager).schedule(TAG, 1, true); order.verify(jobManager).schedule(TAG, 1);
order.verify(jobManager).cancel(TAG); order.verify(jobManager).cancel(TAG);
assertEquals(0, queue.size()); assertEquals(0, queue.size());
} }
@ -183,6 +183,6 @@ public class JobQueueTest {
queue.add(new Reminder(1, now, TYPE_DUE)); queue.add(new Reminder(1, now, TYPE_DUE));
queue.cancel(2); queue.cancel(2);
verify(jobManager).schedule(TAG, now, true); verify(jobManager).schedule(TAG, now);
} }
} }

@ -94,7 +94,6 @@
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Tasks" android:theme="@style/Tasks"
android:allowBackup="true" android:allowBackup="true"
android:fullBackupContent="@xml/backup_config"
android:name=".Tasks" android:name=".Tasks"
android:supportsRtl="true" android:supportsRtl="true"
android:manageSpaceActivity="com.todoroo.astrid.core.OldTaskPreferences"> android:manageSpaceActivity="com.todoroo.astrid.core.OldTaskPreferences">
@ -446,6 +445,21 @@
<service <service
android:name=".scheduling.CalendarNotificationIntentService" android:name=".scheduling.CalendarNotificationIntentService"
android:exported="false" /> android:exported="false" />
<service
android:name=".jobs.AlarmJob"
android:exported="false" />
<service
android:name=".jobs.BackupJob"
android:exported="false" />
<service
android:name=".jobs.MidnightRefreshJob"
android:exported="false" />
<service
android:name=".jobs.RefreshJob"
android:exported="false" />
<service
android:name=".jobs.ReminderJob"
android:exported="false" />
<!-- Uses Library --> <!-- Uses Library -->
<uses-library <uses-library

@ -6,8 +6,6 @@ import com.todoroo.astrid.service.StartupService;
import org.tasks.analytics.Tracker; import org.tasks.analytics.Tracker;
import org.tasks.injection.ApplicationComponent; import org.tasks.injection.ApplicationComponent;
import org.tasks.injection.InjectingApplication; import org.tasks.injection.InjectingApplication;
import org.tasks.jobs.JobManager;
import org.tasks.jobs.JobCreator;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import org.tasks.receivers.TeslaUnreadReceiver; import org.tasks.receivers.TeslaUnreadReceiver;
import org.tasks.themes.ThemeCache; import org.tasks.themes.ThemeCache;
@ -23,8 +21,6 @@ public class Tasks extends InjectingApplication {
@Inject BuildSetup buildSetup; @Inject BuildSetup buildSetup;
@Inject ThemeCache themeCache; @Inject ThemeCache themeCache;
@Inject TeslaUnreadReceiver teslaUnreadReceiver; @Inject TeslaUnreadReceiver teslaUnreadReceiver;
@Inject JobManager jobManager;
@Inject JobCreator jobCreator;
@Override @Override
public void onCreate() { public void onCreate() {
@ -38,8 +34,6 @@ public class Tasks extends InjectingApplication {
AndroidThreeTen.init(this); AndroidThreeTen.init(this);
jobManager.addJobCreator(jobCreator);
flavorSetup.setup(); flavorSetup.setup();
teslaUnreadReceiver.setEnabled(preferences.getBoolean(R.string.p_tesla_unread_enabled, false)); teslaUnreadReceiver.setEnabled(preferences.getBoolean(R.string.p_tesla_unread_enabled, false));

@ -1,5 +1,10 @@
package org.tasks.injection; package org.tasks.injection;
import org.tasks.jobs.AlarmJob;
import org.tasks.jobs.BackupJob;
import org.tasks.jobs.MidnightRefreshJob;
import org.tasks.jobs.RefreshJob;
import org.tasks.jobs.ReminderJob;
import org.tasks.location.GeofenceTransitionsIntentService; import org.tasks.location.GeofenceTransitionsIntentService;
import org.tasks.scheduling.CalendarNotificationIntentService; import org.tasks.scheduling.CalendarNotificationIntentService;
import org.tasks.scheduling.GeofenceSchedulingIntentService; import org.tasks.scheduling.GeofenceSchedulingIntentService;
@ -19,4 +24,14 @@ public interface IntentServiceComponent {
void inject(GeofenceTransitionsIntentService geofenceTransitionsIntentService); void inject(GeofenceTransitionsIntentService geofenceTransitionsIntentService);
void inject(NotificationSchedulerIntentService notificationSchedulerIntentService); void inject(NotificationSchedulerIntentService notificationSchedulerIntentService);
void inject(AlarmJob alarmJob);
void inject(BackupJob backupJob);
void inject(MidnightRefreshJob midnightRefreshJob);
void inject(RefreshJob refreshJob);
void inject(ReminderJob reminderJob);
} }

@ -1,36 +1,31 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.support.annotation.NonNull;
import com.evernote.android.job.Job;
import com.todoroo.astrid.alarms.AlarmService; import com.todoroo.astrid.alarms.AlarmService;
import com.todoroo.astrid.dao.TaskDao; import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.data.Task; import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.reminders.ReminderService;
import org.tasks.Notifier; import org.tasks.Notifier;
import org.tasks.injection.IntentServiceComponent;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import javax.inject.Inject;
public class AlarmJob extends Job { public class AlarmJob extends Job {
public static final String TAG = "job_alarm"; public static final String TAG = "job_alarm";
private final Preferences preferences; @Inject Preferences preferences;
private final AlarmService alarmService; @Inject AlarmService alarmService;
private final Notifier notifier; @Inject Notifier notifier;
private final TaskDao taskDao; @Inject TaskDao taskDao;
public AlarmJob(Preferences preferences, AlarmService alarmService, Notifier notifier, TaskDao taskDao) { public AlarmJob() {
this.preferences = preferences; super(AlarmJob.class.getSimpleName());
this.alarmService = alarmService;
this.notifier = notifier;
this.taskDao = taskDao;
} }
@NonNull
@Override @Override
protected Result onRunJob(Params params) { protected void run() {
try {
if (!preferences.isCurrentlyQuietHours()) { if (!preferences.isCurrentlyQuietHours()) {
for (Alarm alarm : alarmService.removePastDueAlarms()) { for (Alarm alarm : alarmService.removePastDueAlarms()) {
Task task = taskDao.fetch(alarm.getTaskId(), Task.REMINDER_LAST); Task task = taskDao.fetch(alarm.getTaskId(), Task.REMINDER_LAST);
@ -39,9 +34,15 @@ public class AlarmJob extends Job {
} }
} }
} }
return Result.SUCCESS; }
} finally {
@Override
protected void scheduleNext() {
alarmService.scheduleNextJob(); alarmService.scheduleNextJob();
} }
@Override
protected void inject(IntentServiceComponent component) {
component.inject(this);
} }
} }

@ -1,47 +1,54 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull;
import com.evernote.android.job.Job;
import com.todoroo.astrid.backup.TasksXmlExporter; import com.todoroo.astrid.backup.TasksXmlExporter;
import org.tasks.injection.ForApplication;
import org.tasks.injection.IntentServiceComponent;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.util.Arrays; import java.util.Arrays;
import javax.inject.Inject;
import timber.log.Timber; import timber.log.Timber;
public class BackupJob extends Job { public class BackupJob extends MidnightJob {
public static final String TAG = "job_backup"; public static final String TAG = "job_backup";
public static final String BACKUP_FILE_NAME_REGEX = "auto\\.[-\\d]+\\.xml"; //$NON-NLS-1$ public static final String BACKUP_FILE_NAME_REGEX = "auto\\.[-\\d]+\\.xml"; //$NON-NLS-1$
private static final int DAYS_TO_KEEP_BACKUP = 7; private static final int DAYS_TO_KEEP_BACKUP = 7;
private final Context context; @Inject @ForApplication Context context;
private final JobManager jobManager; @Inject JobManager jobManager;
private TasksXmlExporter tasksXmlExporter; @Inject TasksXmlExporter tasksXmlExporter;
private Preferences preferences; @Inject Preferences preferences;
public BackupJob() {
super(BackupJob.class.getSimpleName());
}
BackupJob(Context context, JobManager jobManager, TasksXmlExporter tasksXmlExporter, Preferences preferences) {
this();
public BackupJob(Context context, JobManager jobManager, TasksXmlExporter tasksXmlExporter, Preferences preferences) {
this.context = context; this.context = context;
this.jobManager = jobManager; this.jobManager = jobManager;
this.tasksXmlExporter = tasksXmlExporter; this.tasksXmlExporter = tasksXmlExporter;
this.preferences = preferences; this.preferences = preferences;
} }
@NonNull
@Override @Override
protected Result onRunJob(Params params) { protected void run() {
try {
startBackup(context); startBackup(context);
return Result.SUCCESS;
} finally {
jobManager.scheduleMidnightBackup(false);
} }
@Override
protected void scheduleNext() {
jobManager.scheduleMidnightBackup();
} }
void startBackup(Context context) { void startBackup(Context context) {
@ -83,4 +90,9 @@ public class BackupJob extends Job {
} }
} }
} }
@Override
protected void inject(IntentServiceComponent component) {
component.inject(this);
}
} }

@ -0,0 +1,38 @@
package org.tasks.jobs;
import android.content.Intent;
import org.tasks.analytics.Tracker;
import org.tasks.injection.InjectingIntentService;
import javax.inject.Inject;
import timber.log.Timber;
public abstract class Job extends InjectingIntentService {
@Inject Tracker tracker;
public Job(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
super.onHandleIntent(intent);
Timber.d("onHandleIntent(%s)", intent);
try {
run();
} catch (Exception e) {
tracker.reportException(e);
} finally {
scheduleNext();
}
}
protected abstract void run();
protected abstract void scheduleNext();
}

@ -1,68 +0,0 @@
package org.tasks.jobs;
import android.content.Context;
import com.evernote.android.job.Job;
import com.todoroo.astrid.alarms.AlarmService;
import com.todoroo.astrid.backup.TasksXmlExporter;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.reminders.ReminderService;
import org.tasks.Broadcaster;
import org.tasks.Notifier;
import org.tasks.injection.ApplicationScope;
import org.tasks.injection.ForApplication;
import org.tasks.preferences.Preferences;
import org.tasks.scheduling.RefreshScheduler;
import javax.inject.Inject;
@ApplicationScope
public class JobCreator implements com.evernote.android.job.JobCreator {
private final Context context;
private final Notifier notifier;
private final JobManager jobManager;
private final Broadcaster broadcaster;
private final TasksXmlExporter tasksXmlExporter;
private final Preferences preferences;
private final RefreshScheduler refreshScheduler;
private final AlarmService alarmService;
private final TaskDao taskDao;
private final ReminderService reminderService;
@Inject
public JobCreator(@ForApplication Context context, Notifier notifier, JobManager jobManager,
Broadcaster broadcaster, TasksXmlExporter tasksXmlExporter,
Preferences preferences, RefreshScheduler refreshScheduler,
AlarmService alarmService, TaskDao taskDao, ReminderService reminderService) {
this.context = context;
this.notifier = notifier;
this.jobManager = jobManager;
this.broadcaster = broadcaster;
this.tasksXmlExporter = tasksXmlExporter;
this.preferences = preferences;
this.refreshScheduler = refreshScheduler;
this.alarmService = alarmService;
this.taskDao = taskDao;
this.reminderService = reminderService;
}
@Override
public Job create(String tag) {
switch (tag) {
case ReminderJob.TAG:
return new ReminderJob(preferences, reminderService, notifier);
case AlarmJob.TAG:
return new AlarmJob(preferences, alarmService, notifier, taskDao);
case RefreshJob.TAG:
return new RefreshJob(refreshScheduler, broadcaster);
case MidnightRefreshJob.TAG:
return new MidnightRefreshJob(broadcaster, jobManager);
case BackupJob.TAG:
return new BackupJob(context, jobManager, tasksXmlExporter, preferences);
default:
return null;
}
}
}

@ -1,71 +1,78 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import com.evernote.android.job.JobCreator;
import com.evernote.android.job.JobRequest;
import org.tasks.injection.ApplicationScope; import org.tasks.injection.ApplicationScope;
import org.tasks.injection.ForApplication; import org.tasks.injection.ForApplication;
import org.tasks.scheduling.AlarmManager;
import javax.inject.Inject; import javax.inject.Inject;
import timber.log.Timber;
import static org.tasks.time.DateTimeUtils.currentTimeMillis; import static org.tasks.time.DateTimeUtils.currentTimeMillis;
import static org.tasks.time.DateTimeUtils.nextMidnight; import static org.tasks.time.DateTimeUtils.nextMidnight;
import static org.tasks.time.DateTimeUtils.printTimestamp;
@ApplicationScope @ApplicationScope
public class JobManager { public class JobManager {
private final com.evernote.android.job.JobManager jobManager; private Context context;
private AlarmManager alarmManager;
@Inject @Inject
public JobManager(@ForApplication Context context) { public JobManager(@ForApplication Context context, AlarmManager alarmManager) {
jobManager = com.evernote.android.job.JobManager.create(context); this.context = context;
jobManager.cancelAll(); this.alarmManager = alarmManager;
} }
public void addJobCreator(JobCreator jobCreator) { public void schedule(String tag, long time) {
jobManager.addJobCreator(jobCreator); Timber.d("%s: %s", tag, printTimestamp(time));
alarmManager.wakeup(adjust(time), getPendingIntent(tag));
} }
public void schedule(String tag, long time, boolean cancelCurrent) { public void scheduleRefresh(long time) {
new JobRequest.Builder(tag) Timber.d("%s: %s", RefreshJob.TAG, printTimestamp(time));
.setExact(Math.max(time - currentTimeMillis(), 5000)) alarmManager.noWakeup(adjust(time), getPendingIntent(RefreshJob.class));
.setUpdateCurrent(cancelCurrent)
.build()
.schedule();
} }
public void scheduleRefresh(long time, boolean cancelExisting) { public void scheduleMidnightRefresh() {
new JobRequest.Builder(RefreshJob.TAG) long time = nextMidnight();
.setExact(Math.max(time - currentTimeMillis(), 5000)) Timber.d("%s: %s", MidnightRefreshJob.TAG, printTimestamp(time));
.setUpdateCurrent(cancelExisting) alarmManager.noWakeup(adjust(time), getPendingIntent(MidnightRefreshJob.class));
.build()
.schedule();
} }
public void scheduleMidnightRefresh(boolean cancelExisting) { public void scheduleMidnightBackup() {
scheduleMidnightJob(MidnightRefreshJob.TAG, cancelExisting); long time = nextMidnight();
Timber.d("%s: %s", BackupJob.TAG, printTimestamp(time));
alarmManager.wakeup(adjust(time), getPendingIntent(BackupJob.class));
} }
public void scheduleMidnightBackup(boolean cancelExisting) { public void cancel(String tag) {
scheduleMidnightJob(BackupJob.TAG, cancelExisting); Timber.d("CXL %s", tag);
alarmManager.cancel(getPendingIntent(tag));
} }
private void scheduleMidnightJob(String tag, boolean cancelExisting) { private long adjust(long time) {
long now = System.currentTimeMillis(); return Math.max(time, currentTimeMillis() + 5000);
new JobRequest.Builder(tag)
.setExact(nextMidnight(now) - now)
.setUpdateCurrent(cancelExisting)
.build()
.schedule();
} }
public void cancel(String tag) { private PendingIntent getPendingIntent(String tag) {
jobManager.cancelAllForTag(tag); switch (tag) {
case ReminderJob.TAG:
return getPendingIntent(ReminderJob.class);
case AlarmJob.TAG:
return getPendingIntent(AlarmJob.class);
case RefreshJob.TAG:
return getPendingIntent(RefreshJob.class);
default:
throw new RuntimeException("Unexpected tag: " + tag);
}
} }
public void cancelRefreshes() { private <T> PendingIntent getPendingIntent(Class<T> c) {
jobManager.cancelAllForTag(RefreshJob.TAG); return PendingIntent.getService(context, 0, new Intent(context, c), 0);
} }
} }

@ -79,7 +79,7 @@ public class JobQueue<T extends JobQueueEntry> {
jobManager.cancel(tag); jobManager.cancel(tag);
} }
} else { } else {
jobManager.schedule(tag, nextScheduledTime(), cancelCurrent); jobManager.schedule(tag, nextScheduledTime());
} }
} }

@ -0,0 +1,7 @@
package org.tasks.jobs;
public abstract class MidnightJob extends Job {
public MidnightJob(String name) {
super(name);
}
}

@ -1,31 +1,33 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.support.annotation.NonNull;
import com.evernote.android.job.Job;
import org.tasks.Broadcaster; import org.tasks.Broadcaster;
import org.tasks.injection.IntentServiceComponent;
public class MidnightRefreshJob extends Job { import javax.inject.Inject;
public class MidnightRefreshJob extends MidnightJob {
public static final String TAG = "job_midnight_refresh"; public static final String TAG = "job_midnight_refresh";
private final Broadcaster broadcaster; @Inject Broadcaster broadcaster;
private final JobManager jobManager; @Inject JobManager jobManager;
public MidnightRefreshJob(Broadcaster broadcaster, JobManager jobManager) { public MidnightRefreshJob() {
this.broadcaster = broadcaster; super(MidnightRefreshJob.class.getSimpleName());
this.jobManager = jobManager;
} }
@NonNull
@Override @Override
protected Result onRunJob(Params params) { protected void run() {
try {
broadcaster.refresh(); broadcaster.refresh();
return Result.SUCCESS;
} finally {
jobManager.scheduleMidnightRefresh(false);
} }
@Override
protected void scheduleNext() {
jobManager.scheduleMidnightRefresh();
}
@Override
protected void inject(IntentServiceComponent component) {
component.inject(this);
} }
} }

@ -1,32 +1,34 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.support.annotation.NonNull;
import com.evernote.android.job.Job;
import org.tasks.Broadcaster; import org.tasks.Broadcaster;
import org.tasks.injection.IntentServiceComponent;
import org.tasks.scheduling.RefreshScheduler; import org.tasks.scheduling.RefreshScheduler;
import javax.inject.Inject;
public class RefreshJob extends Job { public class RefreshJob extends Job {
public static final String TAG = "job_refresh"; public static final String TAG = "job_refresh";
private final RefreshScheduler refreshScheduler; @Inject RefreshScheduler refreshScheduler;
private final Broadcaster broadcaster; @Inject Broadcaster broadcaster;
public RefreshJob() {
super(RefreshJob.class.getSimpleName());
}
public RefreshJob(RefreshScheduler refreshScheduler, Broadcaster broadcaster) { @Override
this.refreshScheduler = refreshScheduler; protected void inject(IntentServiceComponent component) {
this.broadcaster = broadcaster; component.inject(this);
} }
@NonNull
@Override @Override
protected Result onRunJob(Params params) { protected void run() {
try {
broadcaster.refresh(); broadcaster.refresh();
return Result.SUCCESS;
} finally {
refreshScheduler.scheduleNext();
} }
@Override
protected void scheduleNext() {
refreshScheduler.scheduleNext();
} }
} }

@ -1,39 +1,41 @@
package org.tasks.jobs; package org.tasks.jobs;
import android.support.annotation.NonNull;
import com.evernote.android.job.Job;
import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.reminders.ReminderService;
import org.tasks.Notifier; import org.tasks.Notifier;
import org.tasks.injection.IntentServiceComponent;
import org.tasks.preferences.Preferences; import org.tasks.preferences.Preferences;
import javax.inject.Inject;
public class ReminderJob extends Job { public class ReminderJob extends Job {
public static final String TAG = "job_reminder"; public static final String TAG = "job_reminder";
private final Preferences preferences; @Inject Preferences preferences;
private final ReminderService reminderService; @Inject ReminderService reminderService;
private final Notifier notifier; @Inject Notifier notifier;
public ReminderJob(Preferences preferences, ReminderService reminderService, Notifier notifier) { public ReminderJob() {
this.preferences = preferences; super(ReminderJob.class.getSimpleName());
this.reminderService = reminderService; }
this.notifier = notifier;
@Override
protected void inject(IntentServiceComponent component) {
component.inject(this);
} }
@NonNull
@Override @Override
protected Result onRunJob(Params params) { protected void run() {
try {
if (!preferences.isCurrentlyQuietHours()) { if (!preferences.isCurrentlyQuietHours()) {
for (Reminder reminder : reminderService.getPastReminders()) { for (Reminder reminder : reminderService.getPastReminders()) {
notifier.triggerTaskNotification(reminder.getId(), reminder.getType()); notifier.triggerTaskNotification(reminder.getId(), reminder.getType());
} }
} }
return Result.SUCCESS;
} finally {
reminderService.scheduleNextJob();
} }
@Override
protected void scheduleNext() {
reminderService.scheduleNextJob();
} }
} }

@ -34,4 +34,15 @@ public class AlarmManager {
alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent); alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent);
} }
} }
@SuppressLint("NewApi")
public void noWakeup(long time, PendingIntent pendingIntent) {
if (atLeastMarshmallow()) {
alarmManager.setExactAndAllowWhileIdle(android.app.AlarmManager.RTC, time, pendingIntent);
} else if (atLeastKitKat()) {
alarmManager.setExact(android.app.AlarmManager.RTC, time, pendingIntent);
} else {
alarmManager.set(android.app.AlarmManager.RTC, time, pendingIntent);
}
}
} }

@ -4,6 +4,7 @@ import com.todoroo.astrid.data.Task;
import org.tasks.injection.ApplicationScope; import org.tasks.injection.ApplicationScope;
import org.tasks.jobs.JobManager; import org.tasks.jobs.JobManager;
import org.tasks.jobs.RefreshJob;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
@ -27,7 +28,7 @@ public class RefreshScheduler {
public void clear() { public void clear() {
jobs.clear(); jobs.clear();
jobManager.cancelRefreshes(); jobManager.cancel(RefreshJob.TAG);
} }
public void scheduleRefresh(Task task) { public void scheduleRefresh(Task task) {
@ -49,24 +50,20 @@ public class RefreshScheduler {
} }
} }
public void scheduleNext() {
scheduleNext(false);
}
private void schedule(long timestamp) { private void schedule(long timestamp) {
SortedSet<Long> upcoming = jobs.tailSet(currentTimeMillis()); SortedSet<Long> upcoming = jobs.tailSet(currentTimeMillis());
boolean reschedule = upcoming.isEmpty() || timestamp < upcoming.first(); boolean reschedule = upcoming.isEmpty() || timestamp < upcoming.first();
jobs.add(timestamp); jobs.add(timestamp);
if (reschedule) { if (reschedule) {
scheduleNext(true); scheduleNext();
} }
} }
private void scheduleNext(boolean cancelCurrent) { public void scheduleNext() {
long now = currentTimeMillis(); long now = currentTimeMillis();
jobs.removeAll(newArrayList(jobs.headSet(now + 1))); jobs.removeAll(newArrayList(jobs.headSet(now + 1)));
if (!jobs.isEmpty()) { if (!jobs.isEmpty()) {
jobManager.scheduleRefresh(jobs.first(), cancelCurrent); jobManager.scheduleRefresh(jobs.first());
} }
} }
} }

@ -32,8 +32,8 @@ public class SchedulerIntentService extends InjectingIntentService {
Timber.d("onHandleIntent(%s)", intent); Timber.d("onHandleIntent(%s)", intent);
jobManager.scheduleMidnightBackup(true); jobManager.scheduleMidnightBackup();
jobManager.scheduleMidnightRefresh(true); jobManager.scheduleMidnightRefresh();
refreshScheduler.clear(); refreshScheduler.clear();
long now = currentTimeMillis(); long now = currentTimeMillis();

@ -23,6 +23,10 @@ public class DateTimeUtils {
MILLIS_PROVIDER = SYSTEM_MILLIS_PROVIDER; MILLIS_PROVIDER = SYSTEM_MILLIS_PROVIDER;
} }
public static long nextMidnight() {
return nextMidnight(currentTimeMillis());
}
public static long nextMidnight(long timestamp) { public static long nextMidnight(long timestamp) {
return newDateTime(timestamp).startOfDay().plusDays(1).getMillis(); return newDateTime(timestamp).startOfDay().plusDays(1).getMillis();
} }

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<exclude domain="sharedpref" path="evernote_jobs.xml" />
<exclude domain="database" path="evernote_jobs.db" />
</full-backup-content>
Loading…
Cancel
Save