С API MediaProjection
, доступными в Android L, можно
захватить содержимое главного экрана (дисплей по умолчанию) в объект Surface, который ваше приложение затем может отправить по сети.
Мне удалось заставить работать VirtualDisplay
, а мой SurfaceView
правильно отображает содержимое экрана.
Что я хочу сделать, так это захватить фрейм, отображаемый в Surface
, и распечатать его в файл. Я пробовал следующее, но все, что я получаю, это черный файл:
Bitmap bitmap = Bitmap.createBitmap
(surfaceView.getWidth(), surfaceView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
surfaceView.draw(canvas);
printBitmapToFile(bitmap);
Любая идея о том, как извлечь отображаемые данные из Surface
?
ИЗМЕНИТЬ
Так как @j__m предположил, что я теперь настраиваю VirtualDisplay
, используя Surface
для 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);
Затем я создаю виртуальный дисплей, передающий Surface
в 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);
Наконец, чтобы получить "скриншот", я получаю Image
из ImageReader
и считываю данные из него:
Image image = imageReader.acquireLatestImage();
byte[] data = getDataFromImage(image);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Проблема заключается в том, что результирующая растровая карта 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;
}
Image
, возвращаемый с acquireLatestImage
, всегда имеет данные с размером по умолчанию 7672320, а декодирование возвращает null
.
Более конкретно, когда ImageReader
пытается получить изображение, возвращается статус ACQUIRE_NO_BUFS
.