mirror of https://github.com/tasks/tasks
Convert WorkManager to Kotlin
parent
7ca58c413c
commit
1b891f2d7e
@ -1,281 +0,0 @@
|
|||||||
package org.tasks.jobs;
|
|
||||||
|
|
||||||
import static com.todoroo.andlib.utility.AndroidUtilities.atLeastOreo;
|
|
||||||
import static com.todoroo.andlib.utility.DateUtilities.now;
|
|
||||||
import static io.reactivex.Single.just;
|
|
||||||
import static io.reactivex.Single.zip;
|
|
||||||
import static org.tasks.date.DateTimeUtils.midnight;
|
|
||||||
import static org.tasks.date.DateTimeUtils.newDateTime;
|
|
||||||
import static org.tasks.db.DbUtils.batch;
|
|
||||||
import static org.tasks.jobs.ReverseGeocodeWork.PLACE_ID;
|
|
||||||
import static org.tasks.time.DateTimeUtils.currentTimeMillis;
|
|
||||||
import static org.tasks.time.DateTimeUtils.printDuration;
|
|
||||||
import static org.tasks.time.DateTimeUtils.printTimestamp;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.AlarmManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.work.BackoffPolicy;
|
|
||||||
import androidx.work.Constraints;
|
|
||||||
import androidx.work.Data;
|
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy;
|
|
||||||
import androidx.work.ExistingWorkPolicy;
|
|
||||||
import androidx.work.NetworkType;
|
|
||||||
import androidx.work.OneTimeWorkRequest;
|
|
||||||
import androidx.work.OneTimeWorkRequest.Builder;
|
|
||||||
import androidx.work.PeriodicWorkRequest;
|
|
||||||
import androidx.work.Worker;
|
|
||||||
import com.google.common.primitives.Longs;
|
|
||||||
import com.todoroo.astrid.data.Task;
|
|
||||||
import io.reactivex.Single;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.tasks.BuildConfig;
|
|
||||||
import org.tasks.R;
|
|
||||||
import org.tasks.data.CaldavDao;
|
|
||||||
import org.tasks.data.GoogleTaskListDao;
|
|
||||||
import org.tasks.data.Place;
|
|
||||||
import org.tasks.injection.ApplicationScope;
|
|
||||||
import org.tasks.injection.ForApplication;
|
|
||||||
import org.tasks.preferences.Preferences;
|
|
||||||
import timber.log.Timber;
|
|
||||||
|
|
||||||
@ApplicationScope
|
|
||||||
public class WorkManager {
|
|
||||||
|
|
||||||
public static final long REMOTE_CONFIG_INTERVAL_HOURS = BuildConfig.DEBUG ? 1 : 12;
|
|
||||||
private static final int MAX_CLEANUP_LENGTH = 500;
|
|
||||||
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_SYNC = "tag_sync";
|
|
||||||
private static final String TAG_BACKGROUND_SYNC = "tag_background_sync";
|
|
||||||
private static final String TAG_REMOTE_CONFIG = "tag_remote_config";
|
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private final Preferences preferences;
|
|
||||||
private final GoogleTaskListDao googleTaskListDao;
|
|
||||||
private final CaldavDao caldavDao;
|
|
||||||
private final AlarmManager alarmManager;
|
|
||||||
private final androidx.work.WorkManager workManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public WorkManager(
|
|
||||||
@ForApplication Context context,
|
|
||||||
Preferences preferences,
|
|
||||||
GoogleTaskListDao googleTaskListDao,
|
|
||||||
CaldavDao caldavDao) {
|
|
||||||
this.context = context;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.googleTaskListDao = googleTaskListDao;
|
|
||||||
this.caldavDao = caldavDao;
|
|
||||||
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
|
||||||
workManager = androidx.work.WorkManager.getInstance(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void afterSave(Task current, Task original) {
|
|
||||||
workManager.enqueue(
|
|
||||||
new OneTimeWorkRequest.Builder(AfterSaveWork.class)
|
|
||||||
.setInputData(AfterSaveWork.getInputData(current, original))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cleanup(Iterable<Long> ids) {
|
|
||||||
batch(
|
|
||||||
ids,
|
|
||||||
MAX_CLEANUP_LENGTH,
|
|
||||||
b ->
|
|
||||||
workManager.enqueue(
|
|
||||||
new Builder(CleanupWork.class)
|
|
||||||
.setInputData(
|
|
||||||
new Data.Builder()
|
|
||||||
.putLongArray(CleanupWork.EXTRA_TASK_IDS, Longs.toArray(b))
|
|
||||||
.build())
|
|
||||||
.build()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sync(boolean immediate) {
|
|
||||||
Constraints constraints =
|
|
||||||
new Constraints.Builder()
|
|
||||||
.setRequiredNetworkType(
|
|
||||||
!immediate
|
|
||||||
&& preferences.getBoolean(R.string.p_background_sync_unmetered_only, false)
|
|
||||||
? NetworkType.UNMETERED
|
|
||||||
: NetworkType.CONNECTED)
|
|
||||||
.build();
|
|
||||||
Builder builder =
|
|
||||||
new Builder(SyncWork.class)
|
|
||||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
|
||||||
.setConstraints(constraints);
|
|
||||||
if (!immediate) {
|
|
||||||
builder.setInitialDelay(1, TimeUnit.MINUTES);
|
|
||||||
}
|
|
||||||
OneTimeWorkRequest request = builder.build();
|
|
||||||
workManager.beginUniqueWork(TAG_SYNC, ExistingWorkPolicy.REPLACE, request).enqueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reverseGeocode(Place place) {
|
|
||||||
if (BuildConfig.DEBUG && place.getId() == 0) {
|
|
||||||
throw new RuntimeException("Missing id");
|
|
||||||
}
|
|
||||||
workManager.enqueue(
|
|
||||||
new Builder(ReverseGeocodeWork.class)
|
|
||||||
.setInputData(new Data.Builder().putLong(PLACE_ID, place.getId()).build())
|
|
||||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
|
||||||
.setConstraints(
|
|
||||||
new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateBackgroundSync() {
|
|
||||||
updateBackgroundSync(null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
|
||||||
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 onlyOnWifi =
|
|
||||||
forceOnlyOnUnmetered == null
|
|
||||||
? preferences.getBoolean(R.string.p_background_sync_unmetered_only, false)
|
|
||||||
: forceOnlyOnUnmetered;
|
|
||||||
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
(forceAccountPresent == null
|
|
||||||
? zip(
|
|
||||||
googleTaskListDao.accountCount(),
|
|
||||||
Single.fromCallable(caldavDao::accountCount),
|
|
||||||
(googleCount, caldavCount) -> googleCount > 0 || caldavCount > 0)
|
|
||||||
: just(forceAccountPresent))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(
|
|
||||||
accountsPresent ->
|
|
||||||
scheduleBackgroundSync(backgroundEnabled && accountsPresent, onlyOnWifi));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleBackgroundSync(boolean enabled, boolean onlyOnUnmetered) {
|
|
||||||
Timber.d("background sync enabled: %s, onlyOnUnmetered: %s", enabled, onlyOnUnmetered);
|
|
||||||
if (enabled) {
|
|
||||||
workManager.enqueueUniquePeriodicWork(
|
|
||||||
TAG_BACKGROUND_SYNC,
|
|
||||||
ExistingPeriodicWorkPolicy.KEEP,
|
|
||||||
new PeriodicWorkRequest.Builder(SyncWork.class, 1, TimeUnit.HOURS)
|
|
||||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
|
||||||
.setConstraints(getNetworkConstraints(onlyOnUnmetered))
|
|
||||||
.build());
|
|
||||||
} else {
|
|
||||||
workManager.cancelUniqueWork(TAG_BACKGROUND_SYNC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleRefresh(long time) {
|
|
||||||
enqueueUnique(TAG_REFRESH, RefreshWork.class, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleMidnightRefresh() {
|
|
||||||
enqueueUnique(TAG_MIDNIGHT_REFRESH, MidnightRefreshWork.class, midnight());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public void scheduleNotification(long time) {
|
|
||||||
time = Math.max(now(), time);
|
|
||||||
|
|
||||||
if (time < currentTimeMillis()) {
|
|
||||||
Intent intent = getNotificationIntent();
|
|
||||||
if (atLeastOreo()) {
|
|
||||||
context.startForegroundService(intent);
|
|
||||||
} else {
|
|
||||||
context.startService(intent);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PendingIntent pendingIntent = getNotificationPendingIntent();
|
|
||||||
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pendingIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleBackup() {
|
|
||||||
long lastBackup = preferences.getLong(R.string.p_last_backup, 0L);
|
|
||||||
enqueueUnique(
|
|
||||||
TAG_BACKUP,
|
|
||||||
BackupWork.class,
|
|
||||||
Math.min(newDateTime(lastBackup).plusDays(1).getMillis(), midnight()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleConfigRefresh() {
|
|
||||||
workManager.enqueueUniquePeriodicWork(
|
|
||||||
TAG_REMOTE_CONFIG,
|
|
||||||
ExistingPeriodicWorkPolicy.KEEP,
|
|
||||||
new PeriodicWorkRequest.Builder(
|
|
||||||
RemoteConfigWork.class, REMOTE_CONFIG_INTERVAL_HOURS, TimeUnit.HOURS)
|
|
||||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
|
||||||
.setConstraints(
|
|
||||||
new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scheduleDriveUpload(Uri uri, boolean purge) {
|
|
||||||
if (!preferences.getBoolean(R.string.p_google_drive_backup, false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Builder builder =
|
|
||||||
new Builder(DriveUploader.class)
|
|
||||||
.setInputData(DriveUploader.getInputData(uri, purge))
|
|
||||||
.setConstraints(getNetworkConstraints());
|
|
||||||
if (purge) {
|
|
||||||
builder.setInitialDelay(new Random().nextInt(3600), TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
workManager.enqueue(builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Constraints getNetworkConstraints() {
|
|
||||||
return getNetworkConstraints(
|
|
||||||
preferences.getBoolean(R.string.p_background_sync_unmetered_only, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Constraints getNetworkConstraints(boolean unmeteredOnly) {
|
|
||||||
return new Constraints.Builder()
|
|
||||||
.setRequiredNetworkType(unmeteredOnly ? NetworkType.UNMETERED : NetworkType.CONNECTED)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enqueueUnique(String key, Class<? extends Worker> c, long time) {
|
|
||||||
long delay = time - now();
|
|
||||||
OneTimeWorkRequest.Builder builder = new Builder(c);
|
|
||||||
if (delay > 0) {
|
|
||||||
builder.setInitialDelay(delay, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
Timber.d("%s: %s (%s)", key, printTimestamp(time), printDuration(delay));
|
|
||||||
workManager.beginUniqueWork(key, ExistingWorkPolicy.REPLACE, builder.build()).enqueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public void cancelNotifications() {
|
|
||||||
Timber.d("cancelNotifications");
|
|
||||||
alarmManager.cancel(getNotificationPendingIntent());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Intent getNotificationIntent() {
|
|
||||||
return new Intent(context, NotificationService.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private PendingIntent getNotificationPendingIntent() {
|
|
||||||
Intent intent = getNotificationIntent();
|
|
||||||
return atLeastOreo()
|
|
||||||
? PendingIntent.getForegroundService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
|
||||||
: PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,228 @@
|
|||||||
|
package org.tasks.jobs
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.work.*
|
||||||
|
import androidx.work.WorkManager
|
||||||
|
import com.todoroo.andlib.utility.AndroidUtilities
|
||||||
|
import com.todoroo.andlib.utility.DateUtilities
|
||||||
|
import com.todoroo.astrid.data.Task
|
||||||
|
import io.reactivex.Single
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.functions.BiFunction
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import org.tasks.BuildConfig
|
||||||
|
import org.tasks.R
|
||||||
|
import org.tasks.data.CaldavDao
|
||||||
|
import org.tasks.data.GoogleTaskListDao
|
||||||
|
import org.tasks.data.Place
|
||||||
|
import org.tasks.date.DateTimeUtils.midnight
|
||||||
|
import org.tasks.date.DateTimeUtils.newDateTime
|
||||||
|
import org.tasks.injection.ApplicationScope
|
||||||
|
import org.tasks.injection.ForApplication
|
||||||
|
import org.tasks.preferences.Preferences
|
||||||
|
import org.tasks.time.DateTimeUtils
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
@ApplicationScope
|
||||||
|
class WorkManager @Inject constructor(
|
||||||
|
@param:ForApplication private val context: Context,
|
||||||
|
private val preferences: Preferences,
|
||||||
|
private val googleTaskListDao: GoogleTaskListDao,
|
||||||
|
private val caldavDao: CaldavDao) {
|
||||||
|
|
||||||
|
private val alarmManager: AlarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
|
private val workManager: WorkManager = WorkManager.getInstance(context)
|
||||||
|
|
||||||
|
fun afterSave(current: Task, original: Task?) =
|
||||||
|
workManager.enqueue(
|
||||||
|
OneTimeWorkRequest.Builder(AfterSaveWork::class.java)
|
||||||
|
.setInputData(AfterSaveWork.getInputData(current, original))
|
||||||
|
.build())
|
||||||
|
|
||||||
|
fun cleanup(ids: Iterable<Long>) = ids.chunked(MAX_CLEANUP_LENGTH) {
|
||||||
|
workManager.enqueue(
|
||||||
|
OneTimeWorkRequest.Builder(CleanupWork::class.java)
|
||||||
|
.setInputData(
|
||||||
|
Data.Builder()
|
||||||
|
.putLongArray(CleanupWork.EXTRA_TASK_IDS, it.toLongArray())
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sync(immediate: Boolean) {
|
||||||
|
val constraints = Constraints.Builder()
|
||||||
|
.setRequiredNetworkType(
|
||||||
|
if (!immediate && preferences.getBoolean(R.string.p_background_sync_unmetered_only, false)) {
|
||||||
|
NetworkType.UNMETERED
|
||||||
|
} else {
|
||||||
|
NetworkType.CONNECTED
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
val builder = OneTimeWorkRequest.Builder(SyncWork::class.java)
|
||||||
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||||
|
.setConstraints(constraints)
|
||||||
|
if (!immediate) {
|
||||||
|
builder.setInitialDelay(1, TimeUnit.MINUTES)
|
||||||
|
}
|
||||||
|
val request = builder.build()
|
||||||
|
workManager.beginUniqueWork(TAG_SYNC, ExistingWorkPolicy.REPLACE, request).enqueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reverseGeocode(place: Place) {
|
||||||
|
if (BuildConfig.DEBUG && place.id == 0L) {
|
||||||
|
throw RuntimeException("Missing id")
|
||||||
|
}
|
||||||
|
workManager.enqueue(
|
||||||
|
OneTimeWorkRequest.Builder(ReverseGeocodeWork::class.java)
|
||||||
|
.setInputData(Data.Builder().putLong(ReverseGeocodeWork.PLACE_ID, place.id).build())
|
||||||
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||||
|
.setConstraints(
|
||||||
|
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
|
||||||
|
.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateBackgroundSync() = updateBackgroundSync(null, null, null)
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
fun updateBackgroundSync(
|
||||||
|
forceAccountPresent: Boolean?,
|
||||||
|
forceBackgroundEnabled: Boolean?,
|
||||||
|
forceOnlyOnUnmetered: Boolean?) {
|
||||||
|
val backgroundEnabled = forceBackgroundEnabled
|
||||||
|
?: preferences.getBoolean(R.string.p_background_sync, true)
|
||||||
|
val onlyOnWifi = forceOnlyOnUnmetered
|
||||||
|
?: preferences.getBoolean(R.string.p_background_sync_unmetered_only, false)
|
||||||
|
(if (forceAccountPresent == null) Single.zip(
|
||||||
|
googleTaskListDao.accountCount(),
|
||||||
|
Single.fromCallable { caldavDao.accountCount() },
|
||||||
|
BiFunction { googleCount: Int, caldavCount: Int -> googleCount > 0 || caldavCount > 0 }) else Single.just(forceAccountPresent))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe { accountsPresent: Boolean -> scheduleBackgroundSync(backgroundEnabled && accountsPresent, onlyOnWifi) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scheduleBackgroundSync(enabled: Boolean, onlyOnUnmetered: Boolean) {
|
||||||
|
Timber.d("background sync enabled: %s, onlyOnUnmetered: %s", enabled, onlyOnUnmetered)
|
||||||
|
if (enabled) {
|
||||||
|
workManager.enqueueUniquePeriodicWork(
|
||||||
|
TAG_BACKGROUND_SYNC,
|
||||||
|
ExistingPeriodicWorkPolicy.KEEP,
|
||||||
|
PeriodicWorkRequest.Builder(SyncWork::class.java, 1, TimeUnit.HOURS)
|
||||||
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||||
|
.setConstraints(getNetworkConstraints(onlyOnUnmetered))
|
||||||
|
.build())
|
||||||
|
} else {
|
||||||
|
workManager.cancelUniqueWork(TAG_BACKGROUND_SYNC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scheduleRefresh(time: Long) = enqueueUnique(TAG_REFRESH, RefreshWork::class.java, time)
|
||||||
|
|
||||||
|
fun scheduleMidnightRefresh() =
|
||||||
|
enqueueUnique(TAG_MIDNIGHT_REFRESH, MidnightRefreshWork::class.java, midnight())
|
||||||
|
|
||||||
|
fun scheduleNotification(scheduledTime: Long) {
|
||||||
|
val time = max(DateUtilities.now(), scheduledTime)
|
||||||
|
if (time < DateTimeUtils.currentTimeMillis()) {
|
||||||
|
val intent = notificationIntent
|
||||||
|
if (AndroidUtilities.atLeastOreo()) {
|
||||||
|
context.startForegroundService(intent)
|
||||||
|
} else {
|
||||||
|
context.startService(intent)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val pendingIntent = notificationPendingIntent
|
||||||
|
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pendingIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scheduleBackup() {
|
||||||
|
enqueueUnique(
|
||||||
|
TAG_BACKUP,
|
||||||
|
BackupWork::class.java,
|
||||||
|
newDateTime(preferences.getLong(R.string.p_last_backup, 0L))
|
||||||
|
.plusDays(1)
|
||||||
|
.millis
|
||||||
|
.coerceAtMost(midnight()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun scheduleConfigRefresh() =
|
||||||
|
workManager.enqueueUniquePeriodicWork(
|
||||||
|
TAG_REMOTE_CONFIG,
|
||||||
|
ExistingPeriodicWorkPolicy.KEEP,
|
||||||
|
PeriodicWorkRequest.Builder(
|
||||||
|
RemoteConfigWork::class.java, REMOTE_CONFIG_INTERVAL_HOURS, TimeUnit.HOURS)
|
||||||
|
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||||
|
.setConstraints(
|
||||||
|
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
|
||||||
|
.build())
|
||||||
|
|
||||||
|
fun scheduleDriveUpload(uri: Uri?, purge: Boolean) {
|
||||||
|
if (!preferences.getBoolean(R.string.p_google_drive_backup, false)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val builder = OneTimeWorkRequest.Builder(DriveUploader::class.java)
|
||||||
|
.setInputData(DriveUploader.getInputData(uri, purge))
|
||||||
|
.setConstraints(networkConstraints)
|
||||||
|
if (purge) {
|
||||||
|
builder.setInitialDelay(Random().nextInt(3600).toLong(), TimeUnit.SECONDS)
|
||||||
|
}
|
||||||
|
workManager.enqueue(builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
private val networkConstraints: Constraints
|
||||||
|
get() = getNetworkConstraints(
|
||||||
|
preferences.getBoolean(R.string.p_background_sync_unmetered_only, false))
|
||||||
|
|
||||||
|
private fun getNetworkConstraints(unmeteredOnly: Boolean) =
|
||||||
|
Constraints.Builder()
|
||||||
|
.setRequiredNetworkType(if (unmeteredOnly) NetworkType.UNMETERED else NetworkType.CONNECTED)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
private fun enqueueUnique(key: String, c: Class<out Worker?>, time: Long) {
|
||||||
|
val delay = time - DateUtilities.now()
|
||||||
|
val builder = OneTimeWorkRequest.Builder(c)
|
||||||
|
if (delay > 0) {
|
||||||
|
builder.setInitialDelay(delay, TimeUnit.MILLISECONDS)
|
||||||
|
}
|
||||||
|
Timber.d("$key: ${DateTimeUtils.printTimestamp(time)} (${DateTimeUtils.printDuration(delay)})")
|
||||||
|
workManager.beginUniqueWork(key, ExistingWorkPolicy.REPLACE, builder.build()).enqueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cancelNotifications() {
|
||||||
|
Timber.d("cancelNotifications")
|
||||||
|
alarmManager.cancel(notificationPendingIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val notificationIntent: Intent
|
||||||
|
get() = Intent(context, NotificationService::class.java)
|
||||||
|
|
||||||
|
private val notificationPendingIntent: PendingIntent
|
||||||
|
get() {
|
||||||
|
return if (AndroidUtilities.atLeastOreo()) {
|
||||||
|
PendingIntent.getForegroundService(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
} else {
|
||||||
|
PendingIntent.getService(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val REMOTE_CONFIG_INTERVAL_HOURS = if (BuildConfig.DEBUG) 1 else 12.toLong()
|
||||||
|
private const val MAX_CLEANUP_LENGTH = 500
|
||||||
|
private const val TAG_BACKUP = "tag_backup"
|
||||||
|
private const val TAG_REFRESH = "tag_refresh"
|
||||||
|
private const val TAG_MIDNIGHT_REFRESH = "tag_midnight_refresh"
|
||||||
|
private const val TAG_SYNC = "tag_sync"
|
||||||
|
private const val TAG_BACKGROUND_SYNC = "tag_background_sync"
|
||||||
|
private const val TAG_REMOTE_CONFIG = "tag_remote_config"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue