Files
android/app/src/main/java/com/hikoncont/service/ProcessMonitorService.kt

299 lines
9.6 KiB
Kotlin
Raw Normal View History

2026-02-11 16:59:49 +08:00
package com.hikoncont.service
import android.app.*
import android.content.Context
import android.content.Intent
import android.os.IBinder
import android.os.PowerManager
import android.util.Log
import androidx.core.app.NotificationCompat
import kotlinx.coroutines.*
import java.io.File
/**
* 进程监控服务
* 监控主进程状态在进程被杀死时立即启动恢复机制
*/
class ProcessMonitorService : Service() {
companion object {
private const val TAG = "ProcessMonitorService"
private const val CHECK_INTERVAL = 1000L // ✅ 激进1秒检查一次进程状态
private const val NOTIFICATION_ID = 9999
private const val CHANNEL_ID = "process_monitor_channel"
// 进程状态文件路径
private const val PROCESS_STATUS_FILE = "process_status.txt"
}
private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private var monitorJob: Job? = null
private var wakeLock: PowerManager.WakeLock? = null
private var notificationManager: NotificationManager? = null
private var isMonitoring = false
override fun onCreate() {
super.onCreate()
Log.i(TAG, "🔍 进程监控服务创建")
// 初始化通知管理器
initNotificationManager()
// 获取WakeLock保活
acquireWakeLock()
// 启动前台服务
startForegroundService()
// 开始监控
startMonitoring()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i(TAG, "🔍 进程监控服务启动命令")
return START_STICKY
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onDestroy() {
Log.i(TAG, "🛑 进程监控服务销毁")
// 释放WakeLock
releaseWakeLock()
// 停止监控
stopMonitoring()
// 启动激进恢复机制
scheduleAggressiveRecovery()
serviceScope.cancel()
super.onDestroy()
}
override fun onTaskRemoved(rootIntent: Intent?) {
Log.w(TAG, "🧹 检测到任务被移除(onTaskRemoved),启动激进恢复")
scheduleAggressiveRecovery()
super.onTaskRemoved(rootIntent)
}
/**
* 初始化通知管理器
*/
private fun initNotificationManager() {
try {
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"进程监控服务",
NotificationManager.IMPORTANCE_LOW
).apply {
description = "监控主进程状态"
setShowBadge(false)
}
notificationManager?.createNotificationChannel(channel)
}
} catch (e: Exception) {
Log.e(TAG, "❌ 初始化通知管理器失败", e)
}
}
/**
* 启动前台服务
*/
private fun startForegroundService() {
try {
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("进程监控服务")
.setContentText("正在监控主进程状态")
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setOngoing(true)
.setPriority(NotificationCompat.PRIORITY_LOW)
.build()
startForeground(NOTIFICATION_ID, notification)
Log.i(TAG, "✅ 前台服务已启动")
} catch (e: Exception) {
Log.e(TAG, "❌ 启动前台服务失败", e)
}
}
/**
* 获取WakeLock保活
*/
private fun acquireWakeLock() {
try {
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"RemoteControl::ProcessMonitorService"
)
wakeLock?.acquire(24 * 60 * 60 * 1000L) // 24小时
Log.i(TAG, "🔋 ProcessMonitorService WakeLock已获取")
} catch (e: Exception) {
Log.e(TAG, "❌ 获取ProcessMonitorService WakeLock失败", e)
}
}
/**
* 释放WakeLock
*/
private fun releaseWakeLock() {
try {
wakeLock?.let {
if (it.isHeld) {
it.release()
Log.i(TAG, "🔋 ProcessMonitorService WakeLock已释放")
}
}
} catch (e: Exception) {
Log.e(TAG, "❌ 释放ProcessMonitorService WakeLock失败", e)
}
}
/**
* 开始监控
*/
private fun startMonitoring() {
if (isMonitoring) {
Log.w(TAG, "⚠️ 进程监控已在运行")
return
}
isMonitoring = true
Log.i(TAG, "🔍 开始进程状态监控")
monitorJob = serviceScope.launch {
while (isActive && isMonitoring) {
try {
// 更新进程状态文件
updateProcessStatus()
// 检查主进程是否存活
if (!isMainProcessAlive()) {
Log.w(TAG, "⚠️ 检测到主进程死亡,启动恢复机制")
scheduleAggressiveRecovery()
}
delay(CHECK_INTERVAL)
} catch (e: Exception) {
Log.e(TAG, "❌ 进程监控异常", e)
delay(CHECK_INTERVAL)
}
}
}
}
/**
* 停止监控
*/
private fun stopMonitoring() {
isMonitoring = false
monitorJob?.cancel()
Log.i(TAG, "🛑 进程监控已停止")
}
/**
* 更新进程状态文件
*/
private fun updateProcessStatus() {
try {
val statusFile = File(filesDir, PROCESS_STATUS_FILE)
val currentTime = System.currentTimeMillis()
val pid = android.os.Process.myPid()
statusFile.writeText("$pid:$currentTime")
} catch (e: Exception) {
Log.e(TAG, "❌ 更新进程状态文件失败", e)
}
}
/**
* 检查主进程是否存活
*/
private fun isMainProcessAlive(): Boolean {
return try {
val statusFile = File(filesDir, PROCESS_STATUS_FILE)
if (!statusFile.exists()) {
return false
}
val content = statusFile.readText()
val parts = content.split(":")
if (parts.size != 2) {
return false
}
val timestamp = parts[1].toLongOrNull() ?: return false
val currentTime = System.currentTimeMillis()
// 如果状态文件超过5秒没有更新认为进程死亡
(currentTime - timestamp) < 5000
} catch (e: Exception) {
Log.e(TAG, "❌ 检查主进程状态失败", e)
false
}
}
/**
* 启动激进恢复机制
*/
private fun scheduleAggressiveRecovery() {
try {
Log.i(TAG, "🚀 启动激进恢复机制")
// 立即启动前台服务
val rcfsIntent = Intent(this, RemoteControlForegroundService::class.java).apply {
action = "RESTART_SERVICE"
}
startForegroundService(rcfsIntent)
// 立即启动保活服务
val keepAliveIntent = Intent(this, KeepAliveService::class.java)
startService(keepAliveIntent)
// 使用AlarmManager安排延迟恢复
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val rcfsPI = PendingIntent.getForegroundService(
this,
(System.currentTimeMillis() % 10000).toInt(),
rcfsIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val keepAlivePI = PendingIntent.getService(
this,
(System.currentTimeMillis() % 10000).toInt() + 1,
keepAliveIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val triggerAt = System.currentTimeMillis() + 50 // 50ms延迟
try {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt, rcfsPI)
} catch (security: SecurityException) {
Log.w(TAG, "Exact alarm denied for process monitor RCFS restart, fallback to inexact wake alarm", security)
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt, rcfsPI)
}
try {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt + 50, keepAlivePI)
} catch (security: SecurityException) {
Log.w(TAG, "Exact alarm denied for process monitor KeepAlive restart, fallback to inexact wake alarm", security)
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt + 50, keepAlivePI)
}
2026-02-11 16:59:49 +08:00
Log.i(TAG, "✅ 激进恢复机制已启动")
} catch (e: Exception) {
Log.e(TAG, "❌ 启动激进恢复机制失败", e)
}
}
}