Parallel Devices¶
The DevicePool lets you run operations across multiple devices concurrently — useful for multi-device testing, fleet management, and parallel automation.
Create a Pool¶
from adbflow import ADB
from adbflow.parallel import DevicePool
async def create_pool():
adb = ADB()
# Get all connected devices
entries = await adb.devices_async()
devices = [await adb.device_async(serial=e.serial) for e in entries]
pool = DevicePool(devices)
print(f"Pool size: {len(pool)}")
Run on All Devices¶
async def parallel_run(pool):
# Run a function on all devices in parallel
async def get_model(device):
return await device.info.model_async()
results = await pool.run_async(get_model)
for result in results:
if isinstance(result, BaseException):
print(f"Error: {result}")
else:
print(f"Model: {result}")
Sequential Execution¶
async def sequential_run(pool):
# Run on devices one at a time
async def install_app(device):
await device.apps.install_async("/path/to/app.apk")
results = await pool.run_sequential_async(install_app)
Filter Devices¶
async def filter_devices(pool):
# Find devices matching a criteria
async def is_samsung(device):
manufacturer = await device.info.manufacturer_async()
return "samsung" in manufacturer.lower()
samsung_devices = await pool.filter_async(is_samsung)
print(f"Found {len(samsung_devices)} Samsung devices")
# Get the first matching device
async def has_large_screen(device):
size = await device.info.screen_size_async()
return size and size.width >= 1440
device = await pool.first_async(has_large_screen)
if device:
print(f"Large screen: {device.serial}")
Iterate Devices¶
async def iterate_pool(pool):
for device in pool:
model = await device.info.model_async()
print(f"{device.serial}: {model}")
Common Patterns¶
Install app on all devices¶
async def install_everywhere(pool):
async def install(device):
await device.apps.install_async("/path/to/app.apk")
await device.apps.start_async("com.example.app")
await pool.run_async(install)
Screenshot all devices¶
async def screenshot_all(pool):
async def capture(device):
model = await device.info.model_async()
await device.media.screenshot.capture_to_file_async(f"{model}.png")
await pool.run_async(capture)
Run test across devices¶
async def multi_device_test(pool):
async def test_login(device):
await device.apps.start_async("com.example.app")
await device.wait_for_text_async("Login", timeout=10.0)
username = await device.ui.find_async(
Selector().resource_id("com.example:id/username")
)
await username.tap_async()
await username.text_input_async("test@test.com")
await device.wait_for_text_async("Dashboard", timeout=10.0)
return True
results = await pool.run_async(test_login)
passed = sum(1 for r in results if r is True)
print(f"Passed: {passed}/{len(pool)}")
Tips¶
run_asyncexecutes in parallel usingasyncio.gather. Errors from individual devices are returned asBaseExceptioninstances, not raised.- Use
run_sequential_asyncwhen operations might conflict (e.g., ADB server resource contention). filter_asyncreturnsDeviceobjects, not a new pool. Wrap them inDevicePool()if needed.