- 删除 .gradle 缓存和锁文件(checksums, executionHistory, fileHashes 等) - 优化 ScreenCaptureManager 截屏逻辑 - 移除 MainActivity, TransparentKeepAliveActivity 中的冗余代码 - 清理多个 KeepAlive 相关服务中的无用导入 - 精简 InstallationStateManager 代码
628 lines
25 KiB
Kotlin
628 lines
25 KiB
Kotlin
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)
|
||
}
|
||
}
|
||
} |