ExamplesSandboxes
Android Sandboxes
Run Android 14 VMs with touch, gesture, and hardware key controls
Android sandboxes expose the sb.mobile interface for touch input, gestures, and hardware keys. Cloud Android works on any host OS. Local Android uses the Android SDK emulator.
Cloud Android VM
Requires
CUA_API_KEY. No Android SDK or emulator needed.# source: examples/sandboxes/test_android_cloud_vm.py
import asyncio
from cua import Image, Sandbox
async def main():
async with Sandbox.ephemeral(
Image.android("14"),
name="example-android-cloud-vm",
) as sb:
screenshot = await sb.screenshot()
with open("screenshot.png", "wb") as f:
f.write(screenshot)
w, h = await sb.screen.size()
print(f"Screen: {w}x{h}")
# Touch controls
await sb.mobile.tap(w // 2, h // 2)
await sb.mobile.home()
asyncio.run(main())Local Android VM
Requires Android SDK with
emulator and adb installed. No API key needed.# source: examples/sandboxes/test_android_local_vm.py
import asyncio
from cua import Image, Sandbox
async def main():
async with Sandbox.ephemeral(
Image.android("14"),
local=True,
name="example-android-local-vm",
) as sb:
screenshot = await sb.screenshot()
with open("screenshot.png", "wb") as f:
f.write(screenshot)
w, h = await sb.screen.size()
print(f"Screen: {w}x{h}")
await sb.mobile.tap(w // 2, h // 2)
await sb.mobile.home()
asyncio.run(main())sb.mobile interface
All touch and hardware key operations go through sb.mobile:
# Tap, long press, double tap
await sb.mobile.tap(x, y)
await sb.mobile.long_press(x, y, duration_ms=1000)
await sb.mobile.double_tap(x, y)
# Swipe and scroll
await sb.mobile.swipe(x1, y1, x2, y2, duration_ms=300)
await sb.mobile.scroll_up()
await sb.mobile.scroll_down()
# Hardware keys
await sb.mobile.home()
await sb.mobile.back()
await sb.mobile.recents()
# Text input
await sb.mobile.type_text("hello world")Multi-touch gestures
Use sb.mobile.gesture() for pinch-to-zoom and other multi-finger inputs. Pass alternating start/end (x, y) pairs — one pair per finger:
w, h = await sb.screen.size()
cx, cy = w // 2, h // 2
# Pinch open (zoom in)
await sb.mobile.gesture(
(cx - 20, cy), (cx - 200, cy), # finger 0
(cx + 20, cy), (cx + 200, cy), # finger 1
)
# Pinch close (zoom out)
await sb.mobile.gesture(
(cx - 200, cy), (cx - 20, cy),
(cx + 200, cy), (cx + 20, cy),
)Was this page helpful?