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
Screenshottylibrary to capture the screenshot. - I'm initializing the
ScreenshotManagerwithin theonCreatemethod of my activity and passing the activity context to the library. - I'm triggering the screenshot capture from the foreground service using the
makeScreenshotmethod of theScreenshotManager.
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?