From 2dfa766b950d5b8a15df29bea0c93963e54a7022 Mon Sep 17 00:00:00 2001 From: sanjeok77 <1+sanjeok77@noreply.localhost> Date: Tue, 25 Aug 2026 01:58:36 +0000 Subject: [PATCH] v0.3.4: update WorkerScheduler.kt --- .../hotdeal/alarm/worker/WorkerScheduler.kt | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/hotdeal/alarm/worker/WorkerScheduler.kt b/app/src/main/java/com/hotdeal/alarm/worker/WorkerScheduler.kt index 85262bb..143dbee 100644 --- a/app/src/main/java/com/hotdeal/alarm/worker/WorkerScheduler.kt +++ b/app/src/main/java/com/hotdeal/alarm/worker/WorkerScheduler.kt @@ -1,6 +1,7 @@ package com.hotdeal.alarm.worker import android.content.Context +import android.util.Log import androidx.work.* import dagger.hilt.android.qualifiers.ApplicationContext import java.util.concurrent.TimeUnit @@ -8,35 +9,40 @@ import javax.inject.Inject import javax.inject.Singleton /** - * Worker 스케줄러 + * 실시간 백그라운드 폴링 통합 스케줄러 * - * 기본 폴� 주기: 2분 - * 배터리/데이터 절약을 위해 최소 2분 권장 + * 1. AlarmManager (AlarmScheduler): Doze Mode에서도 사용자가 지정한 정확한 주기(1분, 2분 등)로 즉시 실행 + * 2. WorkManager (HotDealPollingWorker): OS 백그라운드 작업 관리 및 백업 실행 */ @Singleton class WorkerScheduler @Inject constructor( - @ApplicationContext private val context: Context + @ApplicationContext private val context: Context, + private val alarmScheduler: AlarmScheduler ) { companion object { + private const val TAG = "WorkerScheduler" const val DEFAULT_INTERVAL_MINUTES = 2L const val MIN_INTERVAL_MINUTES = 1L const val MAX_INTERVAL_MINUTES = 60L } /** - * 주기적 폴� 예약 - * @param intervalMinutes 폴� 간격 (분) - 기본 2분 + * 주기적 폴링 예약 (AlarmManager + WorkManager 이중 등록) + * @param intervalMinutes 폴링 간격 (분) */ fun schedulePeriodicPolling(intervalMinutes: Long = DEFAULT_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() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresDeviceIdle(false) .build() - // 유연한 실행 시간 (±25%) val flexTime = (safeInterval * 0.25).toLong().coerceAtLeast(1) val workRequest = PeriodicWorkRequestBuilder( @@ -60,15 +66,17 @@ class WorkerScheduler @Inject constructor( } /** - * 한 번만 실행 + * 즉시 1회 실행 (메인화면 진입 / 새로고침 / 알람 수신 시) */ fun executeOnce() { + Log.d(TAG, "즉시 1회 스크래핑 요청 (executeOnce)") val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() val workRequest = OneTimeWorkRequestBuilder() .setConstraints(constraints) + .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .addTag(HotDealPollingWorker.TAG) .build() @@ -76,22 +84,28 @@ class WorkerScheduler @Inject constructor( } /** - * 폴� 취소 + * 폴링 취소 */ fun cancelPolling() { + Log.d(TAG, "폴링 전체 취소") + alarmScheduler.cancelAlarm() WorkManager.getInstance(context).cancelUniqueWork(HotDealPollingWorker.WORK_NAME) } /** - * 폴� 활성화 여부 확인 + * 폴링 활성화 여부 확인 */ fun isPollingActive(): Boolean { - val workInfos = WorkManager.getInstance(context) - .getWorkInfosForUniqueWork(HotDealPollingWorker.WORK_NAME) - .get() - - return workInfos.any { - it.state == WorkInfo.State.RUNNING || it.state == WorkInfo.State.ENQUEUED + return try { + val workInfos = WorkManager.getInstance(context) + .getWorkInfosForUniqueWork(HotDealPollingWorker.WORK_NAME) + .get() + + workInfos.any { + it.state == WorkInfo.State.RUNNING || it.state == WorkInfo.State.ENQUEUED + } + } catch (e: Exception) { + false } } }