mirror of https://github.com/tasks/tasks
Replace android-job with WorkManager
parent
99c4099787
commit
ba6724a9b0
@ -1,15 +1,15 @@
|
||||
package org.tasks.injection;
|
||||
|
||||
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
|
||||
@Override
|
||||
protected Result onRunJob(@NonNull Params params) {
|
||||
public Result doWork() {
|
||||
JobComponent component =
|
||||
Dagger.get(getContext()).getApplicationComponent().plus(new JobModule());
|
||||
((InjectingApplication) getApplicationContext()).getComponent().plus(new WorkModule());
|
||||
inject(component);
|
||||
return Result.SUCCESS;
|
||||
}
|
@ -1,22 +1,25 @@
|
||||
package org.tasks.injection;
|
||||
|
||||
import dagger.Subcomponent;
|
||||
import org.tasks.jobs.BackupJob;
|
||||
import org.tasks.jobs.CleanupJob;
|
||||
import org.tasks.jobs.NotificationJob;
|
||||
import org.tasks.jobs.RefreshJob;
|
||||
import org.tasks.jobs.SyncJob;
|
||||
import org.tasks.jobs.BackupWork;
|
||||
import org.tasks.jobs.CleanupWork;
|
||||
import org.tasks.jobs.MidnightRefreshWork;
|
||||
import org.tasks.jobs.NotificationWork;
|
||||
import org.tasks.jobs.RefreshWork;
|
||||
import org.tasks.jobs.SyncWork;
|
||||
|
||||
@Subcomponent(modules = JobModule.class)
|
||||
@Subcomponent(modules = WorkModule.class)
|
||||
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