以使用MediaProjection截图 [英] Take a screenshot using MediaProjection
问题描述
随着 MediaProjection
的API在Android的L有效是可能的。
With the MediaProjection
APIs available in Android L it's possible to
捕捉主屏幕上的内容(默认显示)到一个表面对象,你的应用程序就可以通过网络发送
capture the contents of the main screen (the default display) into a Surface object, which your app can then send across the network
我已经设法获得 VirtualDisplay
的工作,而我的 SurfaceView
正确显示画面的内容。
I have managed to get the VirtualDisplay
working, and my SurfaceView
is correctly displaying the content of the screen.
我想要做的就是捕捉在表面
所显示的图像,并将其打印到文件。我曾尝试以下,但我得到的是一个黑色的文件:
What I want to do is to capture a frame displayed in the Surface
, and print it to file. I have tried the following, but all I get is a black file:
Bitmap bitmap = Bitmap.createBitmap
(surfaceView.getWidth(), surfaceView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
surfaceView.draw(canvas);
printBitmapToFile(bitmap);
在如何检索从表面显示的数据,任何想法
?
因此,作为@j__m建议我现在设置了 VirtualDisplay
使用表面
的的ImageReader
:
So as @j__m suggested I'm now setting up the VirtualDisplay
using the Surface
of an ImageReader
:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
displayWidth = size.x;
displayHeight = size.y;
imageReader = ImageReader.newInstance(displayWidth, displayHeight, ImageFormat.JPEG, 5);
然后,我创建虚拟显示器通过了表面
到 MediaProjection
:
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
DisplayMetrics metrics = getResources().getDisplayMetrics();
int density = metrics.densityDpi;
mediaProjection.createVirtualDisplay("test", displayWidth, displayHeight, density, flags,
imageReader.getSurface(), null, projectionHandler);
最后,为了得到一个屏幕截图我获得了图片
从的ImageReader
和读取数据从中:
Finally, in order to get a "screenshot" I acquire an Image
from the ImageReader
and read the data from it:
Image image = imageReader.acquireLatestImage();
byte[] data = getDataFromImage(image);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
的问题是,所产生的位图空
。
The problem is that the resulting bitmap is null
.
这是 getDataFromImage
方法:
public static byte[] getDataFromImage(Image image) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
byte[] data = new byte[buffer.capacity()];
buffer.get(data);
return data;
}
的图片
从返回的 acquireLatestImage
具有与7672320默认大小和解码的回报总是数据空
。
The Image
returned from the acquireLatestImage
has always data with default size of 7672320 and the decoding returns null
.
更具体地讲,当的ImageReader
试图获取,状态 ACQUIRE_NO_BUFS
返回图像。
More specifically, when the ImageReader
tries to acquire an image, the status ACQUIRE_NO_BUFS
is returned.
推荐答案
各种我怎么捕捉屏幕截图SurfaceView的答案(<一href="http://stackoverflow.com/questions/26293819/taking-a-screenshot-of-surfaceview-with-camera-$p$pview-in-it">e.g.这个)仍然适用:你不能这样做,
The various "how do I capture a screen shot of a SurfaceView" answers (e.g. this one) all still apply: you can't do that.
的SurfaceView的表面是一个单独的层,由系统合成的,独立的基于视图的UI层的。表面不是像素缓冲器,而是队列缓冲器,具有生产者 - 消费者安排。您的应用程序是制片方。获取截屏需要你在消费者身边。
The SurfaceView's surface is a separate layer, composited by the system, independent of the View-based UI layer. Surfaces are not buffers of pixels, but rather queues of buffers, with a producer-consumer arrangement. Your app is on the producer side. Getting a screen shot requires you to be on the consumer side.
如果你直接输出,而不是一个SurfaceView到表面纹理,你将有缓冲队列双方在应用程序的过程。您可以渲染输出GLES读它与 glReadPixels阵列()
。 Grafika 有做这样的东西用相机preVIEW的一些例子。
If you direct the output to a SurfaceTexture, instead of a SurfaceView, you will have both sides of the buffer queue in your app process. You can render the output with GLES and read it into an array with glReadPixels()
. Grafika has some examples of doing stuff like this with the Camera preview.
要捕捉的屏幕视频,或者通过网络发送,你会想将它发送给媒体codeC连接codeR输入表面。
To capture the screen as video, or send it over a network, you would want to send it to the input surface of a MediaCodec encoder.
在Android的图形架构的更多详情,请这里。
More details on the Android graphics architecture are available here.
这篇关于以使用MediaProjection截图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!