v0.3.4: add AlarmScheduler.kt
This commit is contained in:
1 parent
5f8299660b
commit
5de2b56c04
1 file changed
+116
@@ -0,0 +1,116 @@
|
||||
package com.hotdeal.alarm.worker
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import com.hotdeal.alarm.receiver.PollingAlarmReceiver
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* 실시간 백그라운드 폴링을 위한 AlarmManager 스케줄러
|
||||
*
|
||||
* WorkManager PeriodicWork의 15분 주기 제한 및 Doze 모드 지연을 극복하기 위해
|
||||
* AlarmManager (setExactAndAllowWhileIdle / setAndAllowWhileIdle)를 사용하여
|
||||
* 사용자가 설정한 주기(1분, 2분, 5분 등)대로 정확하게 백그라운드 수집을 보장합니다.
|
||||
*/
|
||||
@Singleton
|
||||
class AlarmScheduler @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "AlarmScheduler"
|
||||
const val ACTION_POLL_ALARM = "com.hotdeal.alarm.ACTION_POLL_ALARM"
|
||||
private const val REQUEST_CODE = 2001
|
||||
}
|
||||
|
||||
private val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
|
||||
/**
|
||||
* 알람 예약 (Doze mode에서도 정확히 깨어남)
|
||||
* @param intervalMinutes 폴링 간격 (분)
|
||||
*/
|
||||
fun scheduleAlarm(intervalMinutes: Long) {
|
||||
val safeInterval = intervalMinutes.coerceAtLeast(1L)
|
||||
val triggerTime = System.currentTimeMillis() + (safeInterval * 60 * 1000L)
|
||||
|
||||
val intent = Intent(context, PollingAlarmReceiver::class.java).apply {
|
||||
action = ACTION_POLL_ALARM
|
||||
}
|
||||
val pendingIntent = PendingIntent.getBroadcast(
|
||||
context,
|
||||
REQUEST_CODE,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
if (alarmManager.canScheduleExactAlarms()) {
|
||||
alarmManager.setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
triggerTime,
|
||||
pendingIntent
|
||||
)
|
||||
Log.d(TAG, "Exact Alarm 예약 완료: ${safeInterval}분 후 (${triggerTime})")
|
||||
} else {
|
||||
alarmManager.setAndAllowWhileIdle(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
triggerTime,
|
||||
pendingIntent
|
||||
)
|
||||
Log.d(TAG, "Inexact Alarm 예약 완료: ${safeInterval}분 후 (권한 없음)")
|
||||
}
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
alarmManager.setExactAndAllowWhileIdle(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
triggerTime,
|
||||
pendingIntent
|
||||
)
|
||||
Log.d(TAG, "Exact Alarm 예약 완료 (API < 31): ${safeInterval}분 후")
|
||||
} else {
|
||||
alarmManager.setExact(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
triggerTime,
|
||||
pendingIntent
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Alarm 예약 실패: ${e.message}", e)
|
||||
try {
|
||||
alarmManager.setAndAllowWhileIdle(
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
triggerTime,
|
||||
pendingIntent
|
||||
)
|
||||
} catch (fallbackEx: Exception) {
|
||||
Log.e(TAG, "Alarm 폴백 예약도 실패: ${fallbackEx.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 알람 취소
|
||||
*/
|
||||
fun cancelAlarm() {
|
||||
val intent = Intent(context, PollingAlarmReceiver::class.java).apply {
|
||||
action = ACTION_POLL_ALARM
|
||||
}
|
||||
val pendingIntent = PendingIntent.getBroadcast(
|
||||
context,
|
||||
REQUEST_CODE,
|
||||
intent,
|
||||
PendingIntent.FLAG_NO_CREATE or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
|
||||
if (pendingIntent != null) {
|
||||
alarmManager.cancel(pendingIntent)
|
||||
pendingIntent.cancel()
|
||||
Log.d(TAG, "Alarm 취소 완료")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user