Browse Source

fix: resolve LongScreenshotCapture initialization issue

- Extended ScreenCaptureManager interface with getMediaProjection() and getScreenDensity()
- Implemented MediaProjection sharing in ScreenCaptureManagerImpl
- Fixed LongScreenshotCapture initialization with proper MediaProjection access
- Simplified captureFrame() method to directly acquire images from ImageReader
- Added proper initialization checks and error handling in ScreenCaptureService

This resolves the "Cannot start collection - not initialized" error by ensuring
LongScreenshotCapture is properly initialized with the shared MediaProjection
instance during ScreenCaptureService startup.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
feature/pgh-30-long-screenshot-capture
Dan 5 months ago
parent
commit
2d98941f63
  1. 44
      app/src/main/java/com/quillstudios/pokegoalshelper/ScreenCaptureService.kt
  2. 46
      app/src/main/java/com/quillstudios/pokegoalshelper/capture/LongScreenshotCapture.kt
  3. 12
      app/src/main/java/com/quillstudios/pokegoalshelper/capture/ScreenCaptureManager.kt
  4. 10
      app/src/main/java/com/quillstudios/pokegoalshelper/capture/ScreenCaptureManagerImpl.kt

44
app/src/main/java/com/quillstudios/pokegoalshelper/ScreenCaptureService.kt

@ -335,13 +335,26 @@ class ScreenCaptureService : Service() {
// Initialize long screenshot system with shared MediaProjection // Initialize long screenshot system with shared MediaProjection
val screenDimensions = screenCaptureManager.getScreenDimensions() val screenDimensions = screenCaptureManager.getScreenDimensions()
if (screenDimensions != null) { val mediaProjection = screenCaptureManager.getMediaProjection()
val screenDensity = screenCaptureManager.getScreenDensity()
if (screenDimensions != null && mediaProjection != null) {
val (screenWidth, screenHeight) = screenDimensions val (screenWidth, screenHeight) = screenDimensions
longScreenshotCapture = LongScreenshotCapture(this, handler) longScreenshotCapture = LongScreenshotCapture(this, handler)
// Get MediaProjection from screen capture manager (we'll need to add this method) // Initialize with the shared MediaProjection
// For now, we'll initialize it later when we start long screenshot val initialized = longScreenshotCapture!!.initialize(
PGHLog.i(TAG, "✅ Long screenshot system prepared") mediaProjection, screenWidth, screenHeight, screenDensity
)
if (initialized) {
PGHLog.i(TAG, "✅ Long screenshot system initialized successfully")
} else {
PGHLog.e(TAG, "❌ Failed to initialize long screenshot system")
longScreenshotCapture = null
}
} else {
PGHLog.w(TAG, "⚠️ Cannot initialize long screenshot - missing MediaProjection or screen dimensions")
} }
PGHLog.d(TAG, "Screen capture setup complete") PGHLog.d(TAG, "Screen capture setup complete")
@ -1236,22 +1249,6 @@ class ScreenCaptureService : Service() {
{ {
PGHLog.i(TAG, "🚀 Starting long screenshot collection") PGHLog.i(TAG, "🚀 Starting long screenshot collection")
val screenDimensions = screenCaptureManager.getScreenDimensions()
if (screenDimensions == null)
{
PGHLog.e(TAG, "❌ Cannot start long screenshot - no screen dimensions")
enhancedFloatingFAB?.exitLongScreenshotModeExternal()
return
}
val (screenWidth, screenHeight) = screenDimensions
// We need to get the MediaProjection from the screen capture manager
// For now, we'll create a simple workaround by accessing the existing setup
// In a real implementation, we'd need to extend ScreenCaptureManager interface
// Initialize long screenshot capture with mock MediaProjection for now
// This will work because we're using the same MediaProjection instance
longScreenshotCapture?.let { capture -> longScreenshotCapture?.let { capture ->
// Set up callbacks // Set up callbacks
capture.setProgressCallback { count -> capture.setProgressCallback { count ->
@ -1268,13 +1265,18 @@ class ScreenCaptureService : Service() {
} }
} }
// Start collection (we'll initialize the MediaProjection when we implement getMediaProjection) // Start collection
val started = capture.startCollection() val started = capture.startCollection()
if (!started) if (!started)
{ {
PGHLog.e(TAG, "❌ Failed to start long screenshot collection") PGHLog.e(TAG, "❌ Failed to start long screenshot collection")
enhancedFloatingFAB?.exitLongScreenshotModeExternal() enhancedFloatingFAB?.exitLongScreenshotModeExternal()
} else {
PGHLog.i(TAG, "✅ Long screenshot collection started successfully")
} }
} ?: run {
PGHLog.e(TAG, "❌ Long screenshot system not initialized")
enhancedFloatingFAB?.exitLongScreenshotModeExternal()
} }
} }

46
app/src/main/java/com/quillstudios/pokegoalshelper/capture/LongScreenshotCapture.kt

@ -192,43 +192,19 @@ class LongScreenshotCapture(
{ {
PGHLog.d(TAG, "📸 Triggering manual frame capture") PGHLog.d(TAG, "📸 Triggering manual frame capture")
// The capture will be handled by onImageAvailableListener // Force a capture by accessing the ImageReader
// We just need to trigger it by accessing the ImageReader // The VirtualDisplay should automatically provide images to the ImageReader
val latch = CountDownLatch(1) imageReader?.acquireLatestImage()?.let { image ->
var captureSuccess = false PGHLog.d(TAG, "📸 Image acquired from ImageReader, processing...")
handler.post { // Process the image in a coroutine
try captureScope.launch {
{ processImageAsync(image)
// Force a capture by accessing the latest image
imageReader?.acquireLatestImage()?.let { image ->
// This will be processed by onImageAvailableListener
image.close()
captureSuccess = true
}
}
catch (e: Exception)
{
PGHLog.e(TAG, "Error triggering frame capture", e)
}
finally
{
latch.countDown()
} }
} return true
} ?: run {
// Wait for capture to complete PGHLog.w(TAG, "⚠️ No image available from ImageReader")
val completed = latch.await(CAPTURE_TIMEOUT_MS, TimeUnit.MILLISECONDS) return false
if (!completed)
{
PGHLog.e(TAG, "⏱️ Frame capture timed out")
errorCallback?.invoke("Capture timed out")
false
}
else
{
captureSuccess
} }
} }

12
app/src/main/java/com/quillstudios/pokegoalshelper/capture/ScreenCaptureManager.kt

@ -39,6 +39,18 @@ interface ScreenCaptureManager
*/ */
fun getScreenDimensions(): Pair<Int, Int>? fun getScreenDimensions(): Pair<Int, Int>?
/**
* Get the current MediaProjection instance for sharing with other capture systems.
* @return MediaProjection instance or null if not available
*/
fun getMediaProjection(): android.media.projection.MediaProjection?
/**
* Get the current screen density.
* @return Screen density or 0 if not initialized
*/
fun getScreenDensity(): Int
/** /**
* Clean up all resources. Should be called when manager is no longer needed. * Clean up all resources. Should be called when manager is no longer needed.
*/ */

10
app/src/main/java/com/quillstudios/pokegoalshelper/capture/ScreenCaptureManagerImpl.kt

@ -207,6 +207,16 @@ class ScreenCaptureManagerImpl(
} }
} }
override fun getMediaProjection(): MediaProjection?
{
return mediaProjection
}
override fun getScreenDensity(): Int
{
return screenDensity
}
override fun release() override fun release()
{ {
Log.d(TAG, "Releasing ScreenCaptureManager") Log.d(TAG, "Releasing ScreenCaptureManager")

Loading…
Cancel
Save