매일마다 새벽 0시 부터 6시 사이의 랜덤한 시간에 sync()를 호출하는 기능을 WorkManager를 이용해서 구현하기. SyncWorker에는 파라미터가 없어서 최대한 간단히
WorkManager를 사용한 백그라운드 작업 - Kotlin | Android 개발자 | Android Developers
WorkManager periodicity. A deep dive into how WorkManager handle… | by Pietro Maggi | Android Developers | Medium 참고
build.gradle
implementation "androidx.work:work-runtime-ktx:2.3.4"
Settings.kt
val isAutoSync = SettingBoolean("isAutoSync", false)
val nextSyncTime = SettingLong("nextSyncTime", 0L)
val lastSyncTime = SettingLong("lastSyncTime", 0L)
SyncWorker.kt
class SyncWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
if (Settings.isAutoSync.value) {
try {
SyncManager().sync(true)
Settings.lastSyncTime.value = System.currentTimeMillis()
} catch (_: Exception) {
Settings.lastSyncTime.value = -1L
DUtils.notReached()
}
SyncWorkerManager.enqueueWorker(context)
} else {
Settings.nextSyncTime.value = 0L
}
return Result.success()
}
}
object SyncWorkerManager {
private const val UNIQUE_WORK_NAME = "SYNC_WORKER"
fun enqueueWorker(context: Context) {
val currentDate = Calendar.getInstance()
val dueDate = Calendar.getInstance()
val random = SecureRandom()
dueDate.add(Calendar.DATE, 1) // tomorrow
dueDate.set(Calendar.HOUR_OF_DAY, random.nextInt(7)) // 0 ~ 6
dueDate.set(Calendar.MINUTE, random.nextInt(60)) // 0 ~ 59
dueDate.set(Calendar.SECOND, random.nextInt(60)) // 0 ~ 59
if (dueDate.before(currentDate)) {
dueDate.add(Calendar.HOUR_OF_DAY, 24)
}
val timeDiff = dueDate.timeInMillis - currentDate.timeInMillis
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val dailyWorkRequest = OneTimeWorkRequestBuilder<SyncWorker>()
.setConstraints(constraints)
.setInitialDelay(timeDiff, TimeUnit.MILLISECONDS)
.build()
WorkManager
.getInstance(context)
.beginUniqueWork(
UNIQUE_WORK_NAME,
ExistingWorkPolicy.REPLACE,
dailyWorkRequest
)
.enqueue()
Settings.nextSyncTime.value = dueDate.timeInMillis
}
fun cancelWork(context: Context) {
WorkManager.getInstance(context).cancelUniqueWork(UNIQUE_WORK_NAME)
Settings.nextSyncTime.value = 0L
}
}
SettingsMainActivity.kt
private void toggleAutoSyncView() {
boolean isChecked = !autoSyncView.isChecked();
Settings.INSTANCE.isAutoSync().setValue(isChecked);
if (isChecked) {
SyncWorkerManager.INSTANCE.enqueueWorker(this);
} else {
SyncWorkerManager.INSTANCE.cancelWork(this);
}
updateAutoSyncView(isChecked);
}
private void updateAutoSyncView(boolean isAutoSync) {
autoSyncView.setChecked(isAutoSync);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd HH:mm");
StringBuilder sb = new StringBuilder();
sb.append("last: ");
long lastSyncTime = Settings.INSTANCE.getLastSyncTime().getValue();
if (lastSyncTime == 0L) {
sb.append("None");
} else if (lastSyncTime < 0L) {
sb.append("Error");
} else {
sb.append(simpleDateFormat.format(new Date(lastSyncTime)));
}
if (isAutoSync) {
sb.append(", next: ");
long nextSyncTime = Settings.INSTANCE.getNextSyncTime().getValue();
if (nextSyncTime <= 0L) {
sb.append("None");
} else {
sb.append(simpleDateFormat.format(new Date(nextSyncTime)));
}
}
autoSyncView.getDescriptionView().setVisibility(View.VISIBLE);
autoSyncView.getDescriptionView().setText(sb.toString());
}
대충 돌아는 가는 듯..