mirror of https://github.com/tasks/tasks
Replace android-job with WorkManager
parent
99c4099787
commit
ba6724a9b0
@ -1,15 +1,15 @@
|
|||||||
package org.tasks.injection;
|
package org.tasks.injection;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import com.evernote.android.job.Job;
|
import androidx.work.Worker;
|
||||||
|
|
||||||
public abstract class InjectingJob extends Job {
|
public abstract class InjectingWorker extends Worker {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected Result onRunJob(@NonNull Params params) {
|
public Result doWork() {
|
||||||
JobComponent component =
|
JobComponent component =
|
||||||
Dagger.get(getContext()).getApplicationComponent().plus(new JobModule());
|
((InjectingApplication) getApplicationContext()).getComponent().plus(new WorkModule());
|
||||||
inject(component);
|
inject(component);
|
||||||
return Result.SUCCESS;
|
return Result.SUCCESS;
|
||||||
}
|
}
|
@ -1,22 +1,25 @@
|
|||||||
package org.tasks.injection;
|
package org.tasks.injection;
|
||||||
|
|
||||||
import dagger.Subcomponent;
|
import dagger.Subcomponent;
|
||||||
import org.tasks.jobs.BackupJob;
|
import org.tasks.jobs.BackupWork;
|
||||||
import org.tasks.jobs.CleanupJob;
|
import org.tasks.jobs.CleanupWork;
|
||||||
import org.tasks.jobs.NotificationJob;
|
import org.tasks.jobs.MidnightRefreshWork;
|
||||||
import org.tasks.jobs.RefreshJob;
|
import org.tasks.jobs.NotificationWork;
|
||||||
import org.tasks.jobs.SyncJob;
|
import org.tasks.jobs.RefreshWork;
|
||||||
|
import org.tasks.jobs.SyncWork;
|
||||||
|
|
||||||
@Subcomponent(modules = JobModule.class)
|
@Subcomponent(modules = WorkModule.class)
|
||||||
public interface JobComponent {
|
public interface JobComponent {
|
||||||
|
|
||||||
void inject(SyncJob syncJob);
|
void inject(SyncWork syncWork);
|
||||||
|
|
||||||
void inject(NotificationJob notificationJob);
|
void inject(NotificationWork notificationWork);
|
||||||
|
|
||||||
void inject(BackupJob backupJob);
|
void inject(BackupWork backupWork);
|
||||||
|
|
||||||
void inject(RefreshJob refreshJob);
|
void inject(RefreshWork refreshWork);
|
||||||
|
|
||||||
void inject(CleanupJob cleanupJob);
|
void inject(CleanupWork cleanupWork);
|
||||||
|
|
||||||
|
void inject(MidnightRefreshWork midnightRefreshWork);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.tasks.jobs;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import org.tasks.analytics.Tracker;
|
||||||
|
import org.tasks.injection.InjectingWorker;
|
||||||
|
|
||||||
|
public abstract class DailyWork extends InjectingWorker {
|
||||||
|
|
||||||
|
@Inject Tracker tracker;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public final Result doWork() {
|
||||||
|
super.doWork();
|
||||||
|
Result result;
|
||||||
|
try {
|
||||||
|
result = doDailyWork();
|
||||||
|
} catch (Exception e) {
|
||||||
|
tracker.reportException(e);
|
||||||
|
result = Result.FAILURE;
|
||||||
|
}
|
||||||
|
scheduleNext();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Result doDailyWork();
|
||||||
|
|
||||||
|
protected abstract void scheduleNext();
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
package org.tasks.jobs;
|
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import com.evernote.android.job.Job;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.tasks.injection.ApplicationScope;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
@ApplicationScope
|
|
||||||
public class JobCreator implements com.evernote.android.job.JobCreator {
|
|
||||||
|
|
||||||
static final String TAG_BACKUP = "tag_backup";
|
|
||||||
static final String TAG_REFRESH = "tag_refresh";
|
|
||||||
static final String TAG_MIDNIGHT_REFRESH = "tag_midnight_refresh";
|
|
||||||
static final String TAG_NOTIFICATION = "tag_notification";
|
|
||||||
static final String TAG_BACKGROUND_SYNC = "tag_background_sync";
|
|
||||||
static final String TAG_SYNC = "tag_sync";
|
|
||||||
static final String TAG_CLEANUP = "tag_cleanup";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public JobCreator() {}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Job create(@NonNull String tag) {
|
|
||||||
switch (tag) {
|
|
||||||
case TAG_NOTIFICATION:
|
|
||||||
return new NotificationJob();
|
|
||||||
case TAG_SYNC:
|
|
||||||
case TAG_BACKGROUND_SYNC:
|
|
||||||
return new SyncJob();
|
|
||||||
case TAG_BACKUP:
|
|
||||||
return new BackupJob();
|
|
||||||
case TAG_MIDNIGHT_REFRESH:
|
|
||||||
case TAG_REFRESH:
|
|
||||||
return new RefreshJob();
|
|
||||||
case TAG_CLEANUP:
|
|
||||||
return new CleanupJob();
|
|
||||||
default:
|
|
||||||
Timber.e("Unhandled tag: %s", tag);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,142 +0,0 @@
|
|||||||
package org.tasks.jobs;
|
|
||||||
|
|
||||||
import static org.tasks.jobs.CleanupJob.EXTRA_TASK_IDS;
|
|
||||||
import static org.tasks.time.DateTimeUtils.currentTimeMillis;
|
|
||||||
import static org.tasks.time.DateTimeUtils.printTimestamp;
|
|
||||||
|
|
||||||
import com.evernote.android.job.DailyJob;
|
|
||||||
import com.evernote.android.job.JobRequest;
|
|
||||||
import com.evernote.android.job.JobRequest.Builder;
|
|
||||||
import com.evernote.android.job.JobRequest.NetworkType;
|
|
||||||
import com.evernote.android.job.util.support.PersistableBundleCompat;
|
|
||||||
import com.google.common.primitives.Longs;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.tasks.R;
|
|
||||||
import org.tasks.data.CaldavDao;
|
|
||||||
import org.tasks.data.GoogleTaskListDao;
|
|
||||||
import org.tasks.injection.ApplicationScope;
|
|
||||||
import org.tasks.preferences.Preferences;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
@ApplicationScope
|
|
||||||
public class JobManager {
|
|
||||||
|
|
||||||
public static final int JOB_ID_BACKGROUND_SCHEDULER = 2;
|
|
||||||
public static final int JOB_ID_GEOFENCE_TRANSITION = 4;
|
|
||||||
public static final int JOB_ID_GEOFENCE_SCHEDULING = 5;
|
|
||||||
public static final int JOB_ID_TASK_STATUS_CHANGE = 8;
|
|
||||||
public static final int JOB_ID_NOTIFICATION_SCHEDULER = 9;
|
|
||||||
public static final int JOB_ID_CALENDAR_NOTIFICATION = 10;
|
|
||||||
public static final int JOB_ID_TASKER = 11;
|
|
||||||
|
|
||||||
private final com.evernote.android.job.JobManager jobManager;
|
|
||||||
private final Preferences preferences;
|
|
||||||
private final CaldavDao caldavDao;
|
|
||||||
private final GoogleTaskListDao googleTaskListDao;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public JobManager(
|
|
||||||
com.evernote.android.job.JobManager jobManager,
|
|
||||||
Preferences preferences,
|
|
||||||
CaldavDao caldavDao,
|
|
||||||
GoogleTaskListDao googleTaskListDao) {
|
|
||||||
this.jobManager = jobManager;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.caldavDao = caldavDao;
|
|
||||||
this.googleTaskListDao = googleTaskListDao;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cleanup(List<Long> ids) {
|
|
||||||
PersistableBundleCompat extras = new PersistableBundleCompat();
|
|
||||||
extras.putLongArray(EXTRA_TASK_IDS, Longs.toArray(ids));
|
|
||||||
new JobRequest.Builder(JobCreator.TAG_CLEANUP).setExtras(extras).startNow().build().schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleNotification(long time) {
|
|
||||||
Timber.d("schedule notification: %s", printTimestamp(time));
|
|
||||||
new JobRequest.Builder(JobCreator.TAG_NOTIFICATION)
|
|
||||||
.setExact(calculateDelay(time))
|
|
||||||
.setUpdateCurrent(true)
|
|
||||||
.build()
|
|
||||||
.schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleRefresh(long time) {
|
|
||||||
Timber.d("schedule refresh: %s", printTimestamp(time));
|
|
||||||
new JobRequest.Builder(JobCreator.TAG_REFRESH)
|
|
||||||
.setExact(calculateDelay(time))
|
|
||||||
.setUpdateCurrent(true)
|
|
||||||
.build()
|
|
||||||
.schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleMidnightRefresh() {
|
|
||||||
DailyJob.schedule(new Builder(JobCreator.TAG_MIDNIGHT_REFRESH), 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleBackup() {
|
|
||||||
DailyJob.schedule(new Builder(JobCreator.TAG_BACKUP), 0, TimeUnit.HOURS.toMillis(24) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateBackgroundSync() {
|
|
||||||
updateBackgroundSync(null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateBackgroundSync(
|
|
||||||
@Nullable Boolean forceAccountPresent,
|
|
||||||
@Nullable Boolean forceBackgroundEnabled,
|
|
||||||
@Nullable Boolean forceOnlyOnUnmetered) {
|
|
||||||
boolean backgroundEnabled =
|
|
||||||
forceBackgroundEnabled == null
|
|
||||||
? preferences.getBoolean(R.string.p_background_sync, true)
|
|
||||||
: forceBackgroundEnabled;
|
|
||||||
boolean accountsPresent =
|
|
||||||
forceAccountPresent == null
|
|
||||||
? (googleTaskListDao.getAccounts().size() > 0 || caldavDao.getAccounts().size() > 0)
|
|
||||||
: forceAccountPresent;
|
|
||||||
boolean onlyOnWifi =
|
|
||||||
forceOnlyOnUnmetered == null
|
|
||||||
? preferences.getBoolean(R.string.p_background_sync_unmetered_only, false)
|
|
||||||
: forceOnlyOnUnmetered;
|
|
||||||
scheduleBackgroundSynchronization(backgroundEnabled && accountsPresent, onlyOnWifi);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleBackgroundSynchronization(boolean enabled, boolean onlyOnUnmetered) {
|
|
||||||
Timber.d("background sync enabled: %s, onlyOnUnmetered: %s", enabled, onlyOnUnmetered);
|
|
||||||
if (enabled) {
|
|
||||||
new JobRequest.Builder(JobCreator.TAG_BACKGROUND_SYNC)
|
|
||||||
.setPeriodic(TimeUnit.HOURS.toMillis(1))
|
|
||||||
.setRequiredNetworkType(onlyOnUnmetered ? NetworkType.UNMETERED : NetworkType.CONNECTED)
|
|
||||||
.setRequirementsEnforced(true)
|
|
||||||
.setUpdateCurrent(true)
|
|
||||||
.build()
|
|
||||||
.schedule();
|
|
||||||
} else {
|
|
||||||
jobManager.cancelAllForTag(JobCreator.TAG_BACKGROUND_SYNC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void syncNow() {
|
|
||||||
new JobRequest.Builder(JobCreator.TAG_SYNC)
|
|
||||||
.setUpdateCurrent(true)
|
|
||||||
.startNow()
|
|
||||||
.build()
|
|
||||||
.schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancelNotifications() {
|
|
||||||
Timber.d("cancelNotifications");
|
|
||||||
jobManager.cancelAllForTag(JobCreator.TAG_NOTIFICATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
private long calculateDelay(long time) {
|
|
||||||
return Math.max(5000, time - currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addJobCreator(JobCreator jobCreator) {
|
|
||||||
jobManager.addJobCreator(jobCreator);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,27 @@
|
|||||||
|
package org.tasks.jobs;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import org.tasks.LocalBroadcastManager;
|
||||||
|
import org.tasks.injection.JobComponent;
|
||||||
|
|
||||||
|
public class MidnightRefreshWork extends DailyWork {
|
||||||
|
|
||||||
|
@Inject WorkManager workManager;
|
||||||
|
@Inject LocalBroadcastManager localBroadcastManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Result doDailyWork() {
|
||||||
|
localBroadcastManager.broadcastRefresh();
|
||||||
|
return Result.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void scheduleNext() {
|
||||||
|
workManager.scheduleMidnightRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void inject(JobComponent component) {
|
||||||
|
component.inject(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,169 @@
|
|||||||
|
package org.tasks.jobs;
|
||||||
|
|
||||||
|
import static org.tasks.time.DateTimeUtils.currentTimeMillis;
|
||||||
|
import static org.tasks.time.DateTimeUtils.printTimestamp;
|
||||||
|
|
||||||
|
import androidx.work.BackoffPolicy;
|
||||||
|
import androidx.work.Constraints;
|
||||||
|
import androidx.work.Data;
|
||||||
|
import androidx.work.NetworkType;
|
||||||
|
import androidx.work.OneTimeWorkRequest;
|
||||||
|
import androidx.work.PeriodicWorkRequest;
|
||||||
|
import androidx.work.Worker;
|
||||||
|
import com.google.common.primitives.Longs;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import org.tasks.R;
|
||||||
|
import org.tasks.data.CaldavDao;
|
||||||
|
import org.tasks.data.GoogleTaskListDao;
|
||||||
|
import org.tasks.injection.ApplicationScope;
|
||||||
|
import org.tasks.preferences.Preferences;
|
||||||
|
import org.tasks.time.DateTime;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
@ApplicationScope
|
||||||
|
public class WorkManager {
|
||||||
|
|
||||||
|
private static final String TAG_BACKUP = "tag_backup";
|
||||||
|
private static final String TAG_REFRESH = "tag_refresh";
|
||||||
|
private static final String TAG_MIDNIGHT_REFRESH = "tag_midnight_refresh";
|
||||||
|
private static final String TAG_NOTIFICATION = "tag_notification";
|
||||||
|
private static final String TAG_SYNC = "tag_sync";
|
||||||
|
private static final String TAG_BACKGROUND_SYNC = "tag_background_sync";
|
||||||
|
|
||||||
|
private final Preferences preferences;
|
||||||
|
private final GoogleTaskListDao googleTaskListDao;
|
||||||
|
private final CaldavDao caldavDao;
|
||||||
|
private androidx.work.WorkManager workManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public WorkManager(
|
||||||
|
Preferences preferences, GoogleTaskListDao googleTaskListDao, CaldavDao caldavDao) {
|
||||||
|
this.preferences = preferences;
|
||||||
|
this.googleTaskListDao = googleTaskListDao;
|
||||||
|
this.caldavDao = caldavDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
workManager = androidx.work.WorkManager.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanup(List<Long> ids) {
|
||||||
|
workManager.enqueue(
|
||||||
|
new OneTimeWorkRequest.Builder(CleanupWork.class)
|
||||||
|
.setInputData(
|
||||||
|
new Data.Builder()
|
||||||
|
.putLongArray(CleanupWork.EXTRA_TASK_IDS, Longs.toArray(ids))
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncNow() {
|
||||||
|
workManager.enqueue(
|
||||||
|
new OneTimeWorkRequest.Builder(SyncWork.class)
|
||||||
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||||
|
.addTag(TAG_SYNC)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBackgroundSync() {
|
||||||
|
updateBackgroundSync(null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateBackgroundSync(
|
||||||
|
@Nullable Boolean forceAccountPresent,
|
||||||
|
@Nullable Boolean forceBackgroundEnabled,
|
||||||
|
@Nullable Boolean forceOnlyOnUnmetered) {
|
||||||
|
boolean backgroundEnabled =
|
||||||
|
forceBackgroundEnabled == null
|
||||||
|
? preferences.getBoolean(R.string.p_background_sync, true)
|
||||||
|
: forceBackgroundEnabled;
|
||||||
|
boolean accountsPresent =
|
||||||
|
forceAccountPresent == null
|
||||||
|
? (googleTaskListDao.getAccounts().size() > 0 || caldavDao.getAccounts().size() > 0)
|
||||||
|
: forceAccountPresent;
|
||||||
|
boolean onlyOnWifi =
|
||||||
|
forceOnlyOnUnmetered == null
|
||||||
|
? preferences.getBoolean(R.string.p_background_sync_unmetered_only, false)
|
||||||
|
: forceOnlyOnUnmetered;
|
||||||
|
scheduleBackgroundSynchronization(backgroundEnabled && accountsPresent, onlyOnWifi);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleBackgroundSynchronization(boolean enabled, boolean onlyOnUnmetered) {
|
||||||
|
cancelAllForTag(TAG_BACKGROUND_SYNC);
|
||||||
|
Timber.d("background sync enabled: %s, onlyOnUnmetered: %s", enabled, onlyOnUnmetered);
|
||||||
|
if (enabled) {
|
||||||
|
workManager.enqueue(
|
||||||
|
new PeriodicWorkRequest.Builder(SyncWork.class, 1, TimeUnit.HOURS)
|
||||||
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||||
|
.setConstraints(
|
||||||
|
new Constraints.Builder()
|
||||||
|
.setRequiredNetworkType(
|
||||||
|
onlyOnUnmetered ? NetworkType.UNMETERED : NetworkType.CONNECTED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleRefresh(long time) {
|
||||||
|
enqueue(RefreshWork.class, time, TAG_REFRESH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduleMidnightRefresh() {
|
||||||
|
enqueue(
|
||||||
|
MidnightRefreshWork.class,
|
||||||
|
new DateTime(currentTimeMillis()).plusDays(1).startOfDay().getMillis(),
|
||||||
|
TAG_MIDNIGHT_REFRESH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduleNotification(long time, boolean cancelCurrent) {
|
||||||
|
if (cancelCurrent) {
|
||||||
|
cancelNotifications();
|
||||||
|
}
|
||||||
|
enqueue(NotificationWork.class, time, TAG_NOTIFICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheduleBackup() {
|
||||||
|
enqueue(
|
||||||
|
BackupWork.class,
|
||||||
|
new DateTime(currentTimeMillis()).plusDays(1).startOfDay().getMillis(),
|
||||||
|
TAG_BACKUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enqueue(Class<? extends Worker> c, long time, String tag) {
|
||||||
|
long delay = calculateDelay(time);
|
||||||
|
Timber.d("enqueue %s: %s (%sms)", tag, printTimestamp(time), delay);
|
||||||
|
workManager.enqueue(
|
||||||
|
new OneTimeWorkRequest.Builder(c)
|
||||||
|
.setInitialDelay(delay, TimeUnit.MILLISECONDS)
|
||||||
|
.addTag(tag)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelRefresh() {
|
||||||
|
cancelAllForTag(TAG_REFRESH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cancelNotifications() {
|
||||||
|
cancelAllForTag(TAG_NOTIFICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelAllForTag(String tag) {
|
||||||
|
Timber.d("cancelAllWorkByTag(%s)", tag);
|
||||||
|
workManager.cancelAllWorkByTag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long calculateDelay(long time) {
|
||||||
|
return Math.max(5000, time - currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onStartup() {
|
||||||
|
updateBackgroundSync();
|
||||||
|
cancelAllForTag(TAG_MIDNIGHT_REFRESH);
|
||||||
|
scheduleMidnightRefresh();
|
||||||
|
cancelAllForTag(TAG_BACKUP);
|
||||||
|
scheduleBackup();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue