0

I'm trying to get a screenshot of a window, basically a bitmap. I need to also get the screenshot from accelerated hardware devices.

I have implemented the PixelCopy API as the following:

PixelCopyUtils

@RequiresApi(Build.VERSION_CODES.O)
object PixelCopyUtils {

    fun getViewBitmap(window: Window, event: (PixelCopyEvents) -> Unit) {
        val bitmap = Bitmap.createBitmap(window.decorView.rootView.width, window.decorView.rootView.height, Bitmap.Config.ARGB_8888)
        val handlerThread = HandlerThread(PixelCopyUtils::class.java.simpleName)
        handlerThread.start()

        PixelCopy.request(window, bitmap, { copyResult ->
            if (copyResult == PixelCopy.SUCCESS) {
                event(PixelCopyEvents.OnCopySuccess(bitmap))
            } else {
                event(PixelCopyEvents.OnCopyError)
            }
            handlerThread.quitSafely()
        }, Handler(handlerThread.looper))

    }
    sealed interface PixelCopyEvents {
        object OnCopyError: PixelCopyEvents
        data class OnCopySuccess(val bitmap: Bitmap): PixelCopyEvents
    }
}

extension function that is being called from the window I want to get the bitmap from

@RequiresApi(Build.VERSION_CODES.O)
fun Window.onViewDraw(isReady: (Bitmap?) -> Unit) {
    this.decorView.rootView.post {
        PixelCopyUtils.getViewBitmap(this) { event ->
            when(event) {
                PixelCopyUtils.PixelCopyEvents.OnCopyError -> {
                    logging(TAG, "Error while getting the screenshot through PixelCopy API.")
                    isReady(null)
                }
                is PixelCopyUtils.PixelCopyEvents.OnCopySuccess -> {
                    isReady(event.bitmap)
                }
            }
        }
    }
}

It worked many times but I see sometimes I get the following crash:

Exception java.lang.IllegalArgumentException: Window doesn't have a backing surface!
at android.view.PixelCopy.request (PixelCopy.java:278)
at android.view.PixelCopy.request (PixelCopy.java:223)
at android.os.Handler.handleCallback (Handler.java:883)
at android.os.Handler.dispatchMessage (Handler.java:100)
at android.os.Looper.loop (Looper.java:237)
at android.app.ActivityThread.main (ActivityThread.java:8167)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1100)

I don't know why this behaviour is happening if the PixelCopy is triggered after the view is drawn. Thanks in advance.

MACROSystems
  • 415
  • 3
  • 10
  • Does your window have this flag **FLAG_HARDWARE_ACCELERATED**? also you can add hardware acceleration check `if(this.decorView.isHardwareAccelerated)` – Ivan Abakumov Jul 31 '23 at 16:41
  • @IvanAbakumov hello Ivan, I don't really get the suggestion, why would I need a conditional to check fi it is hardware accelerated? You mean that PixelCopy api will crash if it is not hardware accelerated window? – MACROSystems Aug 01 '23 at 08:47
  • Yes, I think the PixelCopy API only works with hardware accelerated windows or is there a parameter in this API that disables this. – Ivan Abakumov Aug 01 '23 at 08:56
  • 1
    Maybe this [article](https://medium.com/tech-takeaways/how-to-programmatically-take-screenshots-with-androids-pixelcopy-api-259d70667360) will help you – Ivan Abakumov Aug 01 '23 at 08:57

0 Answers0