In Detox, what changes when a configuration uses an android.attached device instead of android.emulator, and why does CI usually choose the emulator?
answer
- who owns the device lifecycle
- avdName vs adbName regex
- emulator: launch on a free port
- animations off only on the emulator path
- .* matches anything adb sees
basics
~20 sAn android.emulator device names an AVD that Detox can boot, prepare and shut down itself; an android.attached device is an adb serial pattern Detox can only pick from already-connected devices. CI prefers emulators because they are reproducible and Detox manages them.
solid answer
~40 sWith `android.emulator`, the device query is an `avdName`. Detox reuses a free running emulator of that AVD or launches a new one on a free port, waits for boot, sets the three animation scales to 0 and unlocks the screen; boot options like `bootArgs`, `gpuMode` and `readonly` apply, and it can shut the emulator down at cleanup. With `android.attached`, the query is `adbName`, a regular expression matched against `adb devices` serials; Detox only picks a free, online match and never boots anything, and it leaves the device's animation settings alone. CI prefers the emulator because the AVD pins the image, Detox owns the lifecycle and extra workers get extra instances. Attached devices earn their place for real hardware and vendor-specific checks.
code
javascript · 13 linesmodule.exports = {
devices: {
emulator: {
type: 'android.emulator',
device: { avdName: 'Pixel_7_API_35' },
gpuMode: 'swiftshader_indirect',
},
attached: {
type: 'android.attached',
device: { adbName: '^R5CT[0-9A-Z]+$' }, // a specific phone, not '.*'
},
},
};go deeper
Recall that android.emulator names an AVD Detox can start, while android.attached matches a device that must already be connected.
Explain avdName versus the adbName regex, and what Detox does after allocating each type, including turning off animations on emulators.
Diagnose a CI run with no device to allocate, or an attached run that silently hit a lingering emulator, and choose the type per pipeline stage.
Decide how to split device coverage between cheap repeatable emulator runs and scarcer physical-device runs, and what cadence each deserves.
## Three Android device types A **Detox** device entry in `.detoxrc.js` has a `type` and a `device` query. Android offers `android.emulator`, `android.attached` and `android.genycloud` (cloud-hosted instances). The first two are the everyday choice, and they differ less in what the tests can do than in **who owns the device's lifecycle**. | | `android.emulator` | `android.attached` | |---|---|---| | Query key | `avdName` — an installed AVD name | `adbName` — a regular expression matched against adb serials | | Nothing free and running | Detox launches a new emulator of that AVD on a free port | Detox cannot start one; there is nothing to allocate | | After allocation | Waits for boot, turns off the three system animation scales, unlocks the screen, applies `systemUI` if set | Unlocks the screen, applies `systemUI` if set | | Boot options | `bootArgs`, `gpuMode`, `readonly`, headless boot | Not applicable — the device is already on | | At cleanup | Can shut down emulators it started | Releases the device, leaves it running | ## How `android.emulator` allocates 1. Detox checks that the named AVD exists (`emulator -list-avds` lists valid names). 2. It looks for a running emulator of that AVD that no other Detox worker has registered. 3. If none is free, it picks a free port, launches `emulator-<port>` with the configured boot options and waits for the boot to complete. 4. It sets `animator_duration_scale`, `window_animation_scale` and `transition_animation_scale` to 0 over adb, unlocks the screen and applies any `systemUI` settings. Because Detox can launch more instances on demand, several parallel workers can share one emulator configuration: each gets its own emulator of the same AVD. With multiple workers the docs note that emulators always boot with `-read-only`, so they can share the AVD's disk image. ## How `android.attached` allocates Detox runs `adb devices`, skips entries that are offline or already taken by another worker, and takes the first serial matching the `adbName` pattern. The `detox init` template uses `.*`, which matches **anything adb can see** — including an emulator someone left running. With several devices connected, the docs recommend replacing `.*` with the specific serial. Attached devices also keep their own animation settings; Detox's emulator path turns animations off, the attached path does not, so a physical device with animations on behaves differently from the emulator run. `android.attached` is still the right type when you want real hardware (camera, sensors, a specific vendor build), when a device lab exposes phones over adb, or when you started an emulator yourself with special flags and want Detox to reuse it. ## Why CI usually uses `android.emulator` - **Reproducibility.** The AVD name pins the system image and hardware profile; every job boots the same thing. - **Lifecycle.** Detox boots, prepares and can shut down the emulator itself, so the job script does not need its own boot-and-wait step. - **Scaling.** Extra workers get extra emulator instances automatically, while attached devices must already be plugged in, one per worker. - **Fewer environmental surprises.** No USB disconnects, lock screens or leftover apps from a previous user. A good senior answer names the trade-off, not a rule: emulator runs are cheaper and repeatable; attached-device runs catch hardware and vendor issues. Many teams run the emulator configuration on every change and an attached-device configuration less often. ## Other Android device keys worth knowing - **`-n` / `--device-name`** on `detox test` overrides the query at the command line: for an emulator configuration the value is read as an `avdName`, for an attached one as an `adbName` pattern, so one configuration can target another device for a single run. - **`utilBinaryPaths`** lists helper APKs Detox preinstalls once on Android devices before the run; they survive app reinstalls. - **`forceAdbInstall`** switches installation to plain `adb install` instead of Detox's default push-then-`pm install` scheme, for devices where the default misbehaves. - **`bootArgs`**, **`gpuMode`** and **`readonly`** only mean something when Detox boots the emulator, which is another way of saying they do nothing for `android.attached`. ## A failure worth recognising A suite that runs against an attached phone on a developer's desk and then fails on a build agent with no device connected is not flaky — it has no device to allocate, because `android.attached` never boots anything. Switching the CI configuration to `android.emulator` with an AVD that exists on the agent fixes the cause. The reverse also happens: a lingering emulator matched by `.*` makes an "attached" run silently test on the emulator.
- How do parallel workers get devices with each type?Each worker registers the device it takes so no other worker uses it. With `android.emulator`, a worker that finds no free instance launches another emulator of the same AVD on a new port. With `android.attached`, workers can only share out the devices already connected, so four workers need four matching devices.
- Why can an attached-device run behave differently from the emulator run for the same test?Detox's emulator path turns off the window, transition and animator scales over adb after boot; the attached path only unlocks the screen. A physical phone with animations enabled, a vendor skin or a different screen size can therefore change timing and layout even though the test and app are identical.
saying these in an interview costs you the question
- android.attached boots the phone or emulator if it is not running.
- adbName must be an exact serial; patterns are not supported.
- Detox disables animations the same way on attached devices and emulators.
- An emulator configuration can only ever run one worker.
- The default '.*' pattern only matches physical USB devices.