Skip to content
Latchkey

adb wait-for-device: Block Until the Emulator Is Ready

adb wait-for-device returns as soon as adb sees a device in the device state, which happens well before Android has finished booting.

The most common flaky mobile pipeline waits for the wrong signal. wait-for-device only proves the transport is up; you still have to poll sys.boot_completed before the OS is usable.

What it does

adb wait-for-device (and the transport-specific wait-for-usb-device / wait-for-local-device) blocks the shell until adb reports a matching device in the device state. It does not wait for the Android framework to finish starting, so apps and package manager calls can still fail right after it returns.

Common usage

Terminal
adb wait-for-device
# then wait for the framework to actually finish booting
until [ "$(adb shell getprop sys.boot_completed | tr -d '\r')" = "1" ]; do
  sleep 2
done
adb shell input keyevent 82   # dismiss the lock screen

Options

FormWhat it does
wait-for-deviceWait for any transport to reach the device state
wait-for-usb-deviceWait only for a USB-connected device
wait-for-local-deviceWait only for an emulator / local transport
getprop sys.boot_completedReturns 1 once the framework has booted
getprop init.svc.bootanimReturns stopped when the boot animation ends

In CI

Wrap the poll in an outer timeout (for example timeout 300 bash -c ...) so a stuck emulator fails the job instead of hanging until the runner limit. The reactivecircus/android-emulator-runner action bakes this pattern in; if you launch the emulator yourself, replicate it.

Common errors in CI

A job that hangs forever at this step usually has no emulator starting at all; wait-for-device blocks indefinitely with no timeout. "device offline" right after it returns means you skipped the boot_completed poll. On cold boots, add extra sleep or use -no-snapshot-load so a corrupt snapshot does not leave the device stuck.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →