121 lines
5.4 KiB
Kotlin
121 lines
5.4 KiB
Kotlin
package com.example.shiftalarm
|
|
|
|
import android.content.BroadcastReceiver
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.os.Build
|
|
import android.os.PowerManager
|
|
import android.util.Log
|
|
import kotlinx.coroutines.*
|
|
|
|
class AlarmReceiver : BroadcastReceiver() {
|
|
|
|
private val TAG = "AlarmReceiver"
|
|
|
|
override fun onReceive(context: Context, intent: Intent?) {
|
|
Log.d(TAG, "===== 알람 수신 (Receiver) =====")
|
|
|
|
// 마스터 알람이 꺼져있으면 알람 무시
|
|
val prefs = context.getSharedPreferences("ShiftAlarmPrefs", Context.MODE_PRIVATE)
|
|
if (!ShiftAlarmDefaults.isMasterAlarmEnabled(prefs)) {
|
|
Log.w(TAG, "마스터 알람이 꺼져있어 알람을 무시합니다.")
|
|
return
|
|
}
|
|
|
|
val alarmId = intent?.getIntExtra("EXTRA_ALARM_ID", -1) ?: -1
|
|
val isCustom = intent?.getBooleanExtra("EXTRA_IS_CUSTOM", false) ?: false
|
|
|
|
// 커스텀 알람인 경우 DB에서 여전히 유효한지 확인 (삭제된 알람이 울리는 문제 해결)
|
|
if (isCustom && alarmId != -1) {
|
|
val customAlarmId = intent.getIntExtra("EXTRA_UNIQUE_ID", -1)
|
|
if (customAlarmId != -1) {
|
|
// 비동기로 DB 확인
|
|
val scope = CoroutineScope(Dispatchers.IO)
|
|
scope.launch {
|
|
val repo = ShiftRepository(context)
|
|
val alarms = repo.getAllCustomAlarms()
|
|
val alarmExists = alarms.any { it.id == customAlarmId && it.isEnabled }
|
|
|
|
if (!alarmExists) {
|
|
Log.w(TAG, "삭제된 또는 비활성화된 알람입니다. 무시합니다. (ID: $customAlarmId)")
|
|
scope.cancel()
|
|
return@launch
|
|
}
|
|
|
|
// 알람이 유효하면 직접 AlarmActivity 실행 + Foreground Service 시작
|
|
startAlarm(context, intent)
|
|
scope.cancel()
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
// 일반 알람은 바로 직접 실행
|
|
startAlarm(context, intent)
|
|
}
|
|
|
|
private fun startAlarm(context: Context, intent: Intent?) {
|
|
// WakeLock 획득 (화면 켜기 및 Activity 실행 보장)
|
|
val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
|
|
@Suppress("DEPRECATION")
|
|
val wakeLock = pm.newWakeLock(
|
|
PowerManager.PARTIAL_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP,
|
|
"ShiftAlarm::AlarmWakeLock"
|
|
)
|
|
wakeLock.acquire(30 * 1000L) // 30초 - Activity 실행 및 초기화에 충분한 시간
|
|
|
|
try {
|
|
// 1. Foreground Service 시작 (알림 표시 및 시스템에 알람 실행 중 알림)
|
|
val serviceIntent = Intent(context, AlarmForegroundService::class.java).apply {
|
|
putExtra("EXTRA_SHIFT", intent?.getStringExtra("EXTRA_SHIFT") ?: "근무")
|
|
putExtra("EXTRA_SOUND", intent?.getStringExtra("EXTRA_SOUND"))
|
|
putExtra("EXTRA_SNOOZE", intent?.getIntExtra("EXTRA_SNOOZE", 5) ?: 5)
|
|
putExtra("EXTRA_SNOOZE_REPEAT", intent?.getIntExtra("EXTRA_SNOOZE_REPEAT", 3) ?: 3)
|
|
}
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
context.startForegroundService(serviceIntent)
|
|
} else {
|
|
context.startService(serviceIntent)
|
|
}
|
|
|
|
Log.d(TAG, "ForegroundService 시작 완료")
|
|
|
|
// 2. AlarmActivity 직접 실행 (알람 화면 표시)
|
|
val activityIntent = Intent(context, AlarmActivity::class.java).apply {
|
|
putExtra("EXTRA_SHIFT", intent?.getStringExtra("EXTRA_SHIFT") ?: "근무")
|
|
putExtra("EXTRA_SOUND", intent?.getStringExtra("EXTRA_SOUND"))
|
|
putExtra("EXTRA_SNOOZE", intent?.getIntExtra("EXTRA_SNOOZE", 5) ?: 5)
|
|
putExtra("EXTRA_SNOOZE_REPEAT", intent?.getIntExtra("EXTRA_SNOOZE_REPEAT", 3) ?: 3)
|
|
// 중요: 새 태스크로 실행 (FLAG_ACTIVITY_NEW_TASK)
|
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
// 기존 인스턴스 재사용 및 최상위로 가져오기
|
|
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
// 잠금 화면 위에 표시
|
|
addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
|
|
// 화면 켜기
|
|
addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
|
|
}
|
|
|
|
// 지연 후 Activity 시작 (ForegroundService가 알림을 먼저 표시하도록)
|
|
android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
|
|
try {
|
|
context.startActivity(activityIntent)
|
|
Log.d(TAG, "AlarmActivity 실행 완료")
|
|
} catch (e: Exception) {
|
|
Log.e(TAG, "AlarmActivity 실행 실패", e)
|
|
}
|
|
}, 500)
|
|
|
|
} catch (e: Exception) {
|
|
Log.e(TAG, "알람 실행 실패", e)
|
|
} finally {
|
|
// WakeLock은 Activity가 화면을 켜고 나서 해제
|
|
android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
|
|
if (wakeLock.isHeld) wakeLock.release()
|
|
}, 5000)
|
|
}
|
|
}
|
|
}
|