@ -22,9 +22,10 @@ import android.view.WindowManager
class ScreenCaptureManagerImpl (
class ScreenCaptureManagerImpl (
private val context : Context ,
private val context : Context ,
private val handler : Handler
private val handler : Handler
) : ScreenCaptureManager {
) : ScreenCaptureManager
{
companion object {
companion object
{
private const val TAG = " ScreenCaptureManager "
private const val TAG = " ScreenCaptureManager "
private const val BUFFER_COUNT = 3
private const val BUFFER_COUNT = 3
}
}
@ -41,60 +42,74 @@ class ScreenCaptureManagerImpl(
private var imageCallback : ( ( Image ) -> Unit ) ? = null
private var imageCallback : ( ( Image ) -> Unit ) ? = null
private var isActive = false
private var isActive = false
init {
init
{
mediaProjectionManager = context . getSystemService ( Context . MEDIA_PROJECTION_SERVICE ) as MediaProjectionManager
mediaProjectionManager = context . getSystemService ( Context . MEDIA_PROJECTION_SERVICE ) as MediaProjectionManager
initializeScreenMetrics ( )
initializeScreenMetrics ( )
}
}
private fun initializeScreenMetrics ( ) {
private fun initializeScreenMetrics ( )
val displayMetrics = DisplayMetrics ( )
{
val windowManager = context . getSystemService ( Context . WINDOW_SERVICE ) as WindowManager
val display_metrics = DisplayMetrics ( )
windowManager . defaultDisplay . getMetrics ( displayMetrics )
val window_manager = context . getSystemService ( Context . WINDOW_SERVICE ) as WindowManager
window_manager . defaultDisplay . getMetrics ( display_metrics )
screenWidth = displayM etrics . widthPixels
screenWidth = display_m etrics . widthPixels
screenHeight = displayM etrics . heightPixels
screenHeight = display_m etrics . heightPixels
screenDensity = displayM etrics . densityDpi
screenDensity = display_m etrics . densityDpi
Log . d ( TAG , " Screen metrics initialized: ${screenWidth} x ${screenHeight} , density: $screenDensity " )
Log . d ( TAG , " Screen metrics initialized: ${screenWidth} x ${screenHeight} , density: $screenDensity " )
}
}
private val mediaProjectionCallback = object : MediaProjection . Callback ( ) {
private val mediaProjectionCallback = object : MediaProjection . Callback ( )
override fun onStop ( ) {
{
override fun onStop ( )
{
Log . d ( TAG , " MediaProjection stopped " )
Log . d ( TAG , " MediaProjection stopped " )
stopCapture ( )
stopCapture ( )
}
}
override fun onCapturedContentResize ( width : Int , height : Int ) {
override fun onCapturedContentResize ( width : Int , height : Int )
{
Log . d ( TAG , " Screen size changed: ${width} x ${height} " )
Log . d ( TAG , " Screen size changed: ${width} x ${height} " )
}
}
override fun onCapturedContentVisibilityChanged ( isVisible : Boolean ) {
override fun onCapturedContentVisibilityChanged ( isVisible : Boolean )
{
Log . d ( TAG , " Content visibility changed: $isVisible " )
Log . d ( TAG , " Content visibility changed: $isVisible " )
}
}
}
}
private val onImageAvailableListener = ImageReader . OnImageAvailableListener { reader ->
private val onImageAvailableListener = ImageReader . OnImageAvailableListener { reader ->
try {
try
val image = reader . acquireLatestImage ( )
{
if ( image != null ) {
val captured_image = reader . acquireLatestImage ( )
imageCallback ?. invoke ( image )
if ( captured_image != null )
{
imageCallback ?. invoke ( captured_image )
}
}
} catch ( e : Exception ) {
}
catch ( e : Exception )
{
Log . e ( TAG , " Error in onImageAvailableListener " , e )
Log . e ( TAG , " Error in onImageAvailableListener " , e )
}
}
}
}
override fun startCapture ( resultData : Intent ) : Boolean {
override fun startCapture ( resultData : Intent ) : Boolean
if ( isActive ) {
{
if ( isActive )
{
Log . w ( TAG , " Capture already active " )
Log . w ( TAG , " Capture already active " )
return true
return true
}
}
try {
try
{
Log . d ( TAG , " Starting screen capture " )
Log . d ( TAG , " Starting screen capture " )
mediaProjection = mediaProjectionManager ?. getMediaProjection ( Activity . RESULT_OK , resultData )
mediaProjection = mediaProjectionManager ?. getMediaProjection ( Activity . RESULT_OK , resultData )
if ( mediaProjection == null ) {
if ( mediaProjection == null )
{
Log . e ( TAG , " Failed to get MediaProjection " )
Log . e ( TAG , " Failed to get MediaProjection " )
return false
return false
}
}
@ -118,7 +133,8 @@ class ScreenCaptureManagerImpl(
null
null
)
)
if ( virtualDisplay == null ) {
if ( virtualDisplay == null )
{
Log . e ( TAG , " Failed to create VirtualDisplay " )
Log . e ( TAG , " Failed to create VirtualDisplay " )
cleanupResources ( )
cleanupResources ( )
return false
return false
@ -127,16 +143,19 @@ class ScreenCaptureManagerImpl(
isActive = true
isActive = true
Log . d ( TAG , " Screen capture started successfully " )
Log . d ( TAG , " Screen capture started successfully " )
return true
return true
}
} catch ( e : Exception ) {
catch ( e : Exception )
{
Log . e ( TAG , " Error starting screen capture " , e )
Log . e ( TAG , " Error starting screen capture " , e )
cleanupResources ( )
cleanupResources ( )
return false
return false
}
}
}
}
override fun stopCapture ( ) {
override fun stopCapture ( )
if ( !is Active ) {
{
if ( !is Active )
{
Log . d ( TAG , " Capture not active, nothing to stop " )
Log . d ( TAG , " Capture not active, nothing to stop " )
return
return
}
}
@ -147,37 +166,49 @@ class ScreenCaptureManagerImpl(
Log . d ( TAG , " Screen capture stopped " )
Log . d ( TAG , " Screen capture stopped " )
}
}
private fun cleanupResources ( ) {
private fun cleanupResources ( )
try {
{
try
{
virtualDisplay ?. release ( )
virtualDisplay ?. release ( )
imageReader ?. close ( )
imageReader ?. close ( )
mediaProjection ?. unregisterCallback ( mediaProjectionCallback )
mediaProjection ?. unregisterCallback ( mediaProjectionCallback )
mediaProjection ?. stop ( )
mediaProjection ?. stop ( )
} catch ( e : Exception ) {
}
catch ( e : Exception )
{
Log . e ( TAG , " Error during cleanup " , e )
Log . e ( TAG , " Error during cleanup " , e )
} finally {
}
finally
{
virtualDisplay = null
virtualDisplay = null
imageReader = null
imageReader = null
mediaProjection = null
mediaProjection = null
}
}
}
}
override fun setImageCallback ( callback : ( Image ) -> Unit ) {
override fun setImageCallback ( callback : ( Image ) -> Unit )
{
this . imageCallback = callback
this . imageCallback = callback
Log . d ( TAG , " Image callback set " )
Log . d ( TAG , " Image callback set " )
}
}
override fun isCapturing ( ) : Boolean = isActive
override fun isCapturing ( ) : Boolean = isActive
override fun getScreenDimensions ( ) : Pair < Int , Int > ? {
override fun getScreenDimensions ( ) : Pair < Int , Int > ?
return if ( screenWidth > 0 && screenHeight > 0 ) {
{
return if ( screenWidth > 0 && screenHeight > 0 )
{
Pair ( screenWidth , screenHeight )
Pair ( screenWidth , screenHeight )
} else {
}
else
{
null
null
}
}
}
}
override fun release ( ) {
override fun release ( )
{
Log . d ( TAG , " Releasing ScreenCaptureManager " )
Log . d ( TAG , " Releasing ScreenCaptureManager " )
stopCapture ( )
stopCapture ( )
imageCallback = null
imageCallback = null