How to capture screenshot of current display (not just activity layout) in Android foreground service?

27 Views Asked by At

I'm developing an Android application that uses a foreground service to capture screenshots of the current display, even when the app is not in the foreground. However, the current implementation only captures the layout of my MainActivity, not the entire screen.

Service class detects incoming call ▶ LocalBroadCastReceiver sends intent ▶ MainActivity runs screenshot method and saves the image

- Service class can detect incoming call ✔
- It can send the intent to trigger screen capture ✔
- But current display is not getting capture but rather the activity view which is in background ❌

Most of the stackoverflow answers seem to be either

Here's what I've tried:

  • I'm using the Screenshotty library to capture the screenshot.
  • I'm initializing the ScreenshotManager within the onCreate method of my activity and passing the activity context to the library.
  • I'm triggering the screenshot capture from the foreground service using the makeScreenshot method of the ScreenshotManager.

Screenshotty library The GitHub Link -- Screenshotty

Version 2 -- Currently using a library but same issue persists

// MainActivity.kt
private val screenshotManager = ScreenshotManagerBuilder(this)
    .withCustomActionOrder(ScreenshotActionOrder.pixelCopyFirst())
    .withPermissionRequestCode(REQUEST_SCREENSHOT_PERMISSION)
    .build()

// I am able to take screenshot of the MainActivity <not the current display> and save it
screenshotManager.makeScreenshot()

I have done similar stuff using below method where I am still getting screenshot of MainActivity and not the current display screen

ScreenShotHelper

Version 1:

object ScreenShotHelper {

    fun captureScreenshot(context: Context): Bitmap? {
        val view = (context as Activity).window.decorView.rootView
        val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        view.draw(canvas)
        return bitmap
    }

    // Then use it in MainActivity

}

MainActivity

// MainActivity where I place anonymous BroadCastReceiver to get the intent from service class
// Registered in onCreate()

private val incomingCallReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == ACTION_INCOMING_CALL) {
                
                // Trigger the screen capture method
                val phoneNumber = intent.getStringExtra("phoneNumber")
                receivedPhoneNumber = phoneNumber
                
                // THE VARIOUS METHODS I TRIED 
                // screenshotManager.makeScreenshot() --- Version 2
                // val bitmap = ScreenShotHelper.captureScreenshot(this@MainActivity) --- Version 1
                // bitmap?.let { saveScreenshot(it) } --- Saving to folder works
                
            } else {
                Log.d(TAG, "onReceive: No action found at $CLASS")
            }
        }
    }

override fun onCreate(savedInstanceState: Bundle?) {
        
        LocalBroadcastManager.getInstance(this).registerReceiver(
            incomingCallReceiver,
            IntentFilter(ACTION_INCOMING_CALL)
        );

}

I have these permissions as well

android.Manifest.permission.READ_CALL_LOG,
android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.READ_MEDIA_IMAGES,
android.Manifest.permission.POST_NOTIFICATIONS

Are there any potential drawbacks or limitations to capturing the entire current display screen programmatically (not the activity view) while background/foreground service is detecting incoming call?

0

There are 0 best solutions below