package com.xiaoqu.watch.service import android.app.AlarmManager import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.os.Build import android.os.SystemClock import com.xiaoqu.watch.service.manager.MqttManager import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber import javax.inject.Inject /** * MQTT 连接健康检查广播接收器 * * 通过 AlarmManager.setExactAndAllowWhileIdle() 定期触发, * 在 Doze 模式的维护窗口中检查 MQTT 连接状态,断连则重连。 * 同时确保 MqttService 前台服务存活。 */ @AndroidEntryPoint class MqttAlarmReceiver : BroadcastReceiver() { companion object { /** 检查间隔:5 分钟(Doze 维护窗口至少 10 分钟,5 分钟能抓到窗口期) */ private const val CHECK_INTERVAL_MS = 5 * 60 * 1000L /** 启动定时健康检查 */ fun schedule(context: Context) { val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager val intent = Intent(context, MqttAlarmReceiver::class.java) val pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // setExactAndAllowWhileIdle: Doze 模式下也能触发 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { alarmManager.setExactAndAllowWhileIdle( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + CHECK_INTERVAL_MS, pendingIntent ) } else { alarmManager.setExact( AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + CHECK_INTERVAL_MS, pendingIntent ) } Timber.d("MqttAlarm: 已设置 ${CHECK_INTERVAL_MS / 1000}s 后检查") } /** 取消定时检查 */ fun cancel(context: Context) { val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager val intent = Intent(context, MqttAlarmReceiver::class.java) val pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) alarmManager.cancel(pendingIntent) Timber.d("MqttAlarm: 已取消定时检查") } } @Inject lateinit var mqttManager: MqttManager override fun onReceive(context: Context, intent: Intent) { Timber.d("MqttAlarm: 健康检查触发, isConnected=${mqttManager.isConnected}") // 确保前台服务在运行 MqttService.start(context) // MQTT 断连则重连 if (!mqttManager.isConnected) { Timber.w("MqttAlarm: 连接已断开,触发重连") mqttManager.connect() } // 重新设置下一次闹钟(setExactAndAllowWhileIdle 是一次性的) schedule(context) } }