framebuffer
Framebuffer command takes a high-quality, uncompressed screenshot of the device screen.
Framebuffer command is actually a wrapper for screencap
executable, only uses binary output format instead of PNG. screencap
changed its binary output format in Android 9, so it's difficult for a client to directly parse it without knowing the Android version first. Because framebuffer
command is implemented in ADB daemon and shipped along with screencap
on the device, it always knows the correct format.
Because the binary format contains raw RGB values, it's easier to parse than PNG. However, it's much larger than PNG thus requires more time to transfer and more memory to hold. If the client can decode PNG, it's recommended to use screencap
command instead.
interface AdbFrameBuffer {
bpp: number;
colorSpace?: number;
size: number;
width: number;
height: number;
red_offset: number;
red_length: number;
blue_offset: number;
blue_length: number;
green_offset: number;
green_length: number;
alpha_offset: number;
alpha_length: number;
data: Uint8Array;
}
declare class Adb {
framebuffer(): Promise<AdbFrameBuffer>;
}
Color Space
On Android 9 and above, colorSpace
field is present in the output. The values are:
0
: Unknown1
: sRGB2
: Display P3
Color Format
The four color_offset
and color_length
fields are numbers in bits. Some common color formats are presented by
field | RGBA_8888 | RGBX_8888 | RGB_888 | RGB_565 | BGRA_8888 |
---|---|---|---|---|---|
bpp | 32 | 32 | 24 | 16 | 32 |
red_offset | 0 | 0 | 0 | 11 | 16 |
red_length | 8 | 8 | 8 | 5 | 8 |
green_offset | 8 | 8 | 8 | 5 | 8 |
green_length | 8 | 8 | 8 | 6 | 8 |
blue_offset | 16 | 16 | 16 | 0 | 0 |
blue_length | 8 | 8 | 8 | 5 | 8 |
alpha_offset | 24 | 24 | 0 | 0 | 24 |
alpha_length | 8 | 0 | 0 | 0 | 8 |
- I have only seen RGBA_8888 format
- RGB_565 is actually BGR_565, but Android source code calls it RGB_565
Errors
declare abstract class AdbFrameBufferError extends Error {}
declare class AdbFrameBufferUnsupportedVersionError extends AdbFrameBufferError {}
declare class AdbFrameBufferForbiddenError extends AdbFrameBufferError {}
Framebuffer command has multiple versions, currently Tango supports version 1 and 2. If the device returns an unsupported version, an AdbFrameBufferUnsupportedVersionError
will be thrown.
An AdbFrameBufferForbiddenError
will be thrown when apps on the screen has disabled screen capture by setting the FLAG_SECURE
flag on their windows. Lock screen, video streaming apps, and banking apps are common examples.
Examples
Take a screenshot
const screenshot = await adb.framebuffer();
adb exec-out screencap -p > screenshot.png
Draw the screenshot to a canvas
Assume the screenshot has RGBA8888 color format:
- JavaScript
- TypeScript
const canvas = document.createElement("canvas");
canvas.width = screenshot.width;
canvas.height = screenshot.height;
const context = canvas.getContext("2d");
const imageData = new ImageData(
new Uint8ClampedArray(screenshot.data),
screenshot.width,
screenshot.height,
);
context.putImageData(imageData, 0, 0);
const canvas = document.createElement("canvas");
canvas.width = screenshot.width;
canvas.height = screenshot.height;
const context = canvas.getContext("2d")!;
const imageData = new ImageData(
new Uint8ClampedArray(screenshot.data),
screenshot.width,
screenshot.height,
);
context.putImageData(imageData, 0, 0);
Save the canvas into a PNG file
const url = canvas.toDataURL();
const a = document.createElement("a");
a.href = url;
a.download = `screenshot.png`;
a.click();