I am working on an application that needs to capture a screen into a bitmap for transmission. I am trying to use the new Android 5.0 API android.media.projection to perform screen capture.
The workflow for this API ends with a call.
mediaProjection.createVirtualDisplay("Test Screen", WIDTH, HEIGHT, DPI, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, surface, null, null);
In my initial attempt at this capture, I got a surface object from SurfaceView. This works correctly; the end result is a tiny duplicate of the display on the screen (the result is the effect of the droost )
I thought the function was almost complete, but I then discovered that SurfaceViews (in terms of code) are not readable; You cannot get a bitmap from them.
Looking for other solutions, I came across this question , which has a very similar purpose for mine, and in this thread it was suggested to use ImageReader instead of SurfaceView for the Surface source that you pass to the createVirtualDisplay API call.
However, when I change my code to use ImageReader instead of SurfaceView, I get logcat errors at runtime (with no exceptions), and the callback function for ImageReader is never called. The createVirtualDisplay call also returns the visible virtual object VirtualDisplay.
Here is logcat:
9230-9270/com.android.techrocket9.nanoid E/BufferQueueProducer﹕ [unnamed-9230-0] dequeueBuffer: createGraphicBuffer failed 9230-9246/com.android.techrocket9.nanoid E/BufferQueueProducer﹕ [unnamed-9230-0] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count 9230-9246/com.android.techrocket9.nanoid E/BufferQueueProducer﹕ [unnamed-9230-0] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count 9230-9246/com.android.techrocket9.nanoid E/BufferQueueProducer﹕ [unnamed-9230-0] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count 9230-9246/com.android.techrocket9.nanoid E/BufferQueueProducer﹕ [unnamed-9230-0] dequeueBuffer: can't dequeue multiple buffers without setting the buffer count
This second line is repeated ~ 100 times before it stops occurring.
After going through the debugger, I see that the first error occurs during a call to createVirtualDisplay, and all the others occur after execution returns to the system code.
only the significant result for this error relates to a problem in Kitkat where the API I'm trying to use does not exist. However, I tried the fix suggested here (putting android:hardwareAccelerated="false"
in the manifest). This did not change the behavior of the application.
How can I "set the buffer counter" or otherwise bypass this error and get the screen as a bitmap?
PS My development platform is Nexus 6.
Full code as requested:
MediaProjection mediaProjection = mgr.getMediaProjection(resultCode, data); ImageReader ir = ImageReader.newInstance(WIDTH, HEIGHT, ImageFormat.JPEG, 5); VirtualDisplay v = mediaProjection.createVirtualDisplay("Test Screen", WIDTH, HEIGHT, getApplicationContext().getResources().getDisplayMetrics().densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, ir.getSurface(), null, null);
Edit: Regarding the problem with the artifact, here is the code I use to get the bitmap from the image and display it:
public void onImageAvailable(ImageReader reader) { Image image = null; ByteArrayOutputStream bos = null; try { image = reader.acquireLatestImage(); if (null == image){ return; } bos = new ByteArrayOutputStream(); final Image.Plane[] planes = image.getPlanes(); final ByteBuffer buffer = (ByteBuffer) planes[0].getBuffer().rewind(); final Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888); bitmap.copyPixelsFromBuffer(buffer);