v0.3.4: update WorkerScheduler.kt

This commit is contained in:
sanjeok77 committed 2026-08-25 01:58:36 +00:00
1 parent 5c992f15e6
commit 2dfa766b95
1 file changed
+26 -12
@@ -1,6 +1,7 @@
package com.hotdeal.alarm.worker package com.hotdeal.alarm.worker
import android.content.Context import android.content.Context
import android.util.Log
import androidx.work.* import androidx.work.*
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@@ -8,35 +9,40 @@ import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
/** /**
* Worker 스케줄러 * 실시간 백그라운드 폴링 통합 스케줄러
* *
* 기본 폴� 주기: 2분 * 1. AlarmManager (AlarmScheduler): Doze Mode에서도 사용자가 지정한 정확한 주기(1분, 2분 등)로 즉시 실행
* 배터리/데이터 절약을 위해 최소 2분 권장 * 2. WorkManager (HotDealPollingWorker): OS 백그라운드 작업 관리 및 백업 실행
*/ */
@Singleton @Singleton
class WorkerScheduler @Inject constructor( class WorkerScheduler @Inject constructor(
@ApplicationContext private val context: Context @ApplicationContext private val context: Context,
private val alarmScheduler: AlarmScheduler
) { ) {
companion object { companion object {
private const val TAG = "WorkerScheduler"
const val DEFAULT_INTERVAL_MINUTES = 2L const val DEFAULT_INTERVAL_MINUTES = 2L
const val MIN_INTERVAL_MINUTES = 1L const val MIN_INTERVAL_MINUTES = 1L
const val MAX_INTERVAL_MINUTES = 60L const val MAX_INTERVAL_MINUTES = 60L
} }
/** /**
* 주기적 폴� 예약 * 주기적 폴링 예약 (AlarmManager + WorkManager 이중 등록)
* @param intervalMinutes 폴� 간격 (분) - 기본 2분 * @param intervalMinutes 폴링 간격 (분)
*/ */
fun schedulePeriodicPolling(intervalMinutes: Long = DEFAULT_INTERVAL_MINUTES) { fun schedulePeriodicPolling(intervalMinutes: Long = DEFAULT_INTERVAL_MINUTES) {
// 최소/최대 값 제한
val safeInterval = intervalMinutes.coerceIn(MIN_INTERVAL_MINUTES, MAX_INTERVAL_MINUTES) val safeInterval = intervalMinutes.coerceIn(MIN_INTERVAL_MINUTES, MAX_INTERVAL_MINUTES)
Log.d(TAG, "주기적 폴링 예약 시작: ${safeInterval}분 간격")
// 1. AlarmManager 기반 정확한 주기 알람 예약 (Doze mode 관통)
alarmScheduler.scheduleAlarm(safeInterval)
// 2. WorkManager 기반 백업 주기 작업 예약
val constraints = Constraints.Builder() val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) .setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresDeviceIdle(false) .setRequiresDeviceIdle(false)
.build() .build()
// 유연한 실행 시간 (±25%)
val flexTime = (safeInterval * 0.25).toLong().coerceAtLeast(1) val flexTime = (safeInterval * 0.25).toLong().coerceAtLeast(1)
val workRequest = PeriodicWorkRequestBuilder<HotDealPollingWorker>( val workRequest = PeriodicWorkRequestBuilder<HotDealPollingWorker>(
@@ -60,15 +66,17 @@ class WorkerScheduler @Inject constructor(
} }
/** /**
* 한 번만 실행 * 즉시 1회 실행 (메인화면 진입 / 새로고침 / 알람 수신 시)
*/ */
fun executeOnce() { fun executeOnce() {
Log.d(TAG, "즉시 1회 스크래핑 요청 (executeOnce)")
val constraints = Constraints.Builder() val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) .setRequiredNetworkType(NetworkType.CONNECTED)
.build() .build()
val workRequest = OneTimeWorkRequestBuilder<HotDealPollingWorker>() val workRequest = OneTimeWorkRequestBuilder<HotDealPollingWorker>()
.setConstraints(constraints) .setConstraints(constraints)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.addTag(HotDealPollingWorker.TAG) .addTag(HotDealPollingWorker.TAG)
.build() .build()
@@ -76,22 +84,28 @@ class WorkerScheduler @Inject constructor(
} }
/** /**
* 폴� 취소 * 폴링 취소
*/ */
fun cancelPolling() { fun cancelPolling() {
Log.d(TAG, "폴링 전체 취소")
alarmScheduler.cancelAlarm()
WorkManager.getInstance(context).cancelUniqueWork(HotDealPollingWorker.WORK_NAME) WorkManager.getInstance(context).cancelUniqueWork(HotDealPollingWorker.WORK_NAME)
} }
/** /**
* 폴� 활성화 여부 확인 * 폴링 활성화 여부 확인
*/ */
fun isPollingActive(): Boolean { fun isPollingActive(): Boolean {
return try {
val workInfos = WorkManager.getInstance(context) val workInfos = WorkManager.getInstance(context)
.getWorkInfosForUniqueWork(HotDealPollingWorker.WORK_NAME) .getWorkInfosForUniqueWork(HotDealPollingWorker.WORK_NAME)
.get() .get()
return workInfos.any { workInfos.any {
it.state == WorkInfo.State.RUNNING || it.state == WorkInfo.State.ENQUEUED it.state == WorkInfo.State.RUNNING || it.state == WorkInfo.State.ENQUEUED
} }
} catch (e: Exception) {
false
}
} }
} }