添加前台服务+WakeLock保活MQTT连接,请求电池优化白名单绕过Doze限制, AlarmManager每5分钟健康检查断连自动重连。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
86 lines
3.1 KiB
Kotlin
86 lines
3.1 KiB
Kotlin
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)
|
||
}
|
||
}
|