Files
and-bak/app/src/main/java/com/hikoncont/service/ProcessMonitorService.kt
2026-02-11 16:59:49 +08:00

288 lines
9.0 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.*
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延迟
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt, rcfsPI)
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt + 50, keepAlivePI)
Log.i(TAG, "✅ 激进恢复机制已启动")
} catch (e: Exception) {
Log.e(TAG, "❌ 启动激进恢复机制失败", e)
}
}
}