以使用MediaProjection截图 [英] Take a screenshot using MediaProjection

查看:1864
本文介绍了以使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆