android_screenshot
Capture screenshots from Android devices or emulators to save locally for debugging, testing, or documentation purposes.
Instructions
Capture screenshot from Android device or emulator
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| serial | Yes | Device serial number (use android_devices_list to get available devices) | |
| outputPath | Yes | Local path where screenshot will be saved (e.g., ./screenshot.png) | |
| options | No |
Implementation Reference
- src/tools/android/media.ts:102-193 (handler)The handler function that implements the core logic for capturing Android screenshots using ADB screencap command, pulling the file locally, cleaning up temp files, and handling errors.handler: async (args: any) => { const parsed = AndroidScreenshotSchema.parse(args); try { // Ensure output directory exists const outputDir = path.dirname(parsed.outputPath); await fs.mkdir(outputDir, { recursive: true }); const adbArgs = ['-s', parsed.serial, 'exec-out', 'screencap']; if (parsed.options?.format === 'png') { adbArgs.push('-p'); // PNG format } if (parsed.options?.display !== undefined) { adbArgs.push('-d', parsed.options.display.toString()); } // Capture screenshot to temporary location first const tempPath = `/sdcard/screenshot_${Date.now()}.png`; const captureResult = await processExecutor.execute('adb', [ '-s', parsed.serial, 'shell', 'screencap', '-p', tempPath ], { timeout: 30000, }); if (captureResult.exitCode !== 0) { return { success: false, error: { code: 'SCREENSHOT_CAPTURE_FAILED', message: 'Failed to capture screenshot on device', details: captureResult.stderr } }; } // Pull screenshot to local machine const pullResult = await processExecutor.execute('adb', [ '-s', parsed.serial, 'pull', tempPath, parsed.outputPath ], { timeout: 30000, }); // Clean up temporary file await processExecutor.execute('adb', [ '-s', parsed.serial, 'shell', 'rm', tempPath ], { timeout: 10000, }); if (pullResult.exitCode === 0) { // Verify file was created let fileStats; try { fileStats = await fs.stat(parsed.outputPath); } catch { throw new Error(`Screenshot file was not created at ${parsed.outputPath}`); } return { success: true, data: { screenshotPath: parsed.outputPath, fileSize: fileStats.size, format: parsed.options?.format || 'png', device: parsed.serial, timestamp: new Date().toISOString() } }; } else { return { success: false, error: { code: 'SCREENSHOT_PULL_FAILED', message: 'Failed to pull screenshot from device', details: pullResult.stderr } }; } } catch (error: any) { return { success: false, error: { code: 'SCREENSHOT_ERROR', message: error.message, details: error } }; } }
- src/tools/android/media.ts:23-34 (schema)Zod schema used for input validation and parsing within the android_screenshot handler.* Zod validation schema for android_screenshot tool. * * @type {z.ZodObject} */ const AndroidScreenshotSchema = z.object({ serial: z.string().min(1), outputPath: z.string().min(1), options: z.object({ format: z.enum(['png', 'raw']).default('png'), display: z.number().optional(), }).optional(), });
- src/tools/android/media.ts:70-194 (registration)Tool registration in the Map, defining name, description, JSON inputSchema, and reference to the handler function.tools.set('android_screenshot', { name: 'android_screenshot', description: 'Capture screenshot from Android device or emulator', inputSchema: { type: 'object', properties: { serial: { type: 'string', description: 'Device serial number (use android_devices_list to get available devices)' }, outputPath: { type: 'string', description: 'Local path where screenshot will be saved (e.g., ./screenshot.png)' }, options: { type: 'object', properties: { format: { type: 'string', enum: ['png', 'raw'], description: 'Screenshot format', default: 'png' }, display: { type: 'number', description: 'Display ID for multi-display devices' } } } }, required: ['serial', 'outputPath'] }, handler: async (args: any) => { const parsed = AndroidScreenshotSchema.parse(args); try { // Ensure output directory exists const outputDir = path.dirname(parsed.outputPath); await fs.mkdir(outputDir, { recursive: true }); const adbArgs = ['-s', parsed.serial, 'exec-out', 'screencap']; if (parsed.options?.format === 'png') { adbArgs.push('-p'); // PNG format } if (parsed.options?.display !== undefined) { adbArgs.push('-d', parsed.options.display.toString()); } // Capture screenshot to temporary location first const tempPath = `/sdcard/screenshot_${Date.now()}.png`; const captureResult = await processExecutor.execute('adb', [ '-s', parsed.serial, 'shell', 'screencap', '-p', tempPath ], { timeout: 30000, }); if (captureResult.exitCode !== 0) { return { success: false, error: { code: 'SCREENSHOT_CAPTURE_FAILED', message: 'Failed to capture screenshot on device', details: captureResult.stderr } }; } // Pull screenshot to local machine const pullResult = await processExecutor.execute('adb', [ '-s', parsed.serial, 'pull', tempPath, parsed.outputPath ], { timeout: 30000, }); // Clean up temporary file await processExecutor.execute('adb', [ '-s', parsed.serial, 'shell', 'rm', tempPath ], { timeout: 10000, }); if (pullResult.exitCode === 0) { // Verify file was created let fileStats; try { fileStats = await fs.stat(parsed.outputPath); } catch { throw new Error(`Screenshot file was not created at ${parsed.outputPath}`); } return { success: true, data: { screenshotPath: parsed.outputPath, fileSize: fileStats.size, format: parsed.options?.format || 'png', device: parsed.serial, timestamp: new Date().toISOString() } }; } else { return { success: false, error: { code: 'SCREENSHOT_PULL_FAILED', message: 'Failed to pull screenshot from device', details: pullResult.stderr } }; } } catch (error: any) { return { success: false, error: { code: 'SCREENSHOT_ERROR', message: error.message, details: error } }; } } });