π‘ Device Manager & ADB Manager Dialog
March 29, 2026 Β· View on GitHub
β Back to README
Complete reference for device selection β how the system auto-detects devices, when and how the picker dialog appears, the IP connection flow, and the
DeviceManagersingleton API.
DeviceManager Singleton
The single source of truth for which ADB device to target. Every ADB command in the system builds its argument list using DeviceManager.instance.adbArgs.
State
| Field | Type | Default | Meaning |
|---|---|---|---|
_deviceId | String? | null | Resolved target: serial, "ip:port", or "-d" |
_needsDeviceSelection | bool | false | When true, the boot flow must show the dialog before starting |
Properties
| Property | Return | Description |
|---|---|---|
deviceId | String | Current target; returns "-d" if nothing set |
needsDeviceSelection | bool | Whether user must pick a device |
isUsb | bool | _deviceId == "-d" |
isWifi | bool | _deviceId is an IP address |
adbArgs | List<String> | ["-d"] or ["-s", _deviceId] |
Key Methods
setFromArgs(List<String> args)
Called from the application entry point with CLI arguments:
args = ["--usb"] β _deviceId = "-d"
args = ["192.168.1.5"] β _deviceId = "192.168.1.5:5555"
args = ["192.168.1.5:5555"] β _deviceId = "192.168.1.5:5555"
args = [] β autoDetect()
autoDetect()
Calls AdbProvider.instance.getDevices() then:
| Result | Action |
|---|---|
| 0 devices | _deviceId = "-d" Β· needsDeviceSelection = true |
| 1 device (USB serial) | _deviceId = "-d" Β· needsDeviceSelection = false |
| 1 device (IP) | _deviceId = "ip:port" Β· needsDeviceSelection = false |
| 2+ devices | _deviceId = first device Β· needsDeviceSelection = true |
selectDevice(String id)
Called when the user picks a device in the dialog:
id = "emulator-5554" β _deviceId = "-d" (USB/serial β force USB flag)
id = "192.168.1.5:5555" β _deviceId = "192.168.1.5:5555" (keep IP)
needsDeviceSelection β false
When Does the Dialog Appear?
The dialog is shown in exactly two situations β never speculatively:
Situation 1 β Pre-Boot (no device or multiple devices)
App launched β setFromArgs() β autoDetect()
β
βββ needsDeviceSelection == true?
β
βΌ
DeviceManagerDialog opens
β
User picks device or types IP
β
selectDevice(id) called
β
Boot sequence begins
Situation 2 β Post-Error (connection failure during boot)
Boot sequence running...
β
βββ EXCEPTION thrown
β
βββ _isConnectionError(message)?
β
βΌ
_canPickDevice = true
Error panel shown in boot screen
"Open ADB Manager" button appears
β
User taps button β dialog opens
β
User picks device
β
_resetBootState() β _runBoot() (retry)
Key design decision: The dialog is never auto-popped during a connection error. The user sees the error message first, then deliberately opens the manager. This ensures they understand what failed before choosing how to fix it.
DeviceManagerDialog β UI Reference
Opened via: showDialog() with barrierColor: Colors.transparent
The transparent barrier means the InitScreen background (animated gradient) remains fully visible behind the dialog β no dark overlay.
Layout
βββββββββββββββββββββββββββββββββββββββββββββββ
β π± Android Dex β ADB Manager β
β Tap a device to connect instantly β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β β [Reason banner β why dialog opened] β β only shown if reason provided
βββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββ DEVICE LIST (tap = immediate connect) ββ β
β β π USB Device βΊ β β
β β ABC123XYZ β tap to connect β β
β βββββββββββββββββββββββββββββββββββββββββββ€ β
β β πΆ 192.168.1.100:5555 βΊ β β
β β Wi-Fi ADB β tap to connect β β
β βββββββββββββββββββββββββββββββββββββββββββ β
β β
β [or "Scanning for ADB devicesβ¦" spinner] β
β [or "No ADB devices found" empty state] β
β β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β Connect via IP Address β
β ββββββββββββββββββββββββββ βββββββββββββ β
β β 192.168.1.100 β β Connect β β
β ββββββββββββββββββββββββββ βββββββββββββ β
β β [Inline error if IP fails] β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β [ βΊ Refresh Devices ] [ β Cancel ] β
βββββββββββββββββββββββββββββββββββββββββββββββ
Interaction Model
| Action | Result |
|---|---|
| Tap any device row | Navigator.pop(deviceId) immediately β dialog closes |
| Type IP + press Connect / Enter | adb connect ip:5555 runs; success β Navigator.pop(ip) |
| IP connection fails | Inline error message replaces Connect spinner |
| Press Refresh | Rescans adb devices; list reloads with fade-in animation |
| Press Cancel | Navigator.pop(null) β dialog closes, no device set |
IP Connection Flow (Detail)
User types "192.168.1.100" β presses Connect
β
βΌ
ip = "192.168.1.100:5555" (auto-appends port)
AdbProvider.run(["connect", "192.168.1.100:5555"])
β
ββ Output contains "connected" or "already connected"
β β
β βββ Navigator.pop("192.168.1.100:5555") β
β β DeviceManager.selectDevice("192.168.1.100:5555")
β β Boot sequence starts / retries
β
ββ Any other output / exception
β
βββ _ipError = "Unable to connect to 192.168.1.100:5555
β verify the IP and try again."
Spinner β Connect button restored
_DeviceRow Widget
Each row in the device list. Hover-aware with animated border and arrow:
- USB devices (no
:) β USB icon Β· label "USB Device" Β· sublabel "ABC123 β tap to connect" - Wi-Fi devices (contains
:) β Wi-Fi icon Β· label shows IP Β· sublabel "Wi-Fi ADB β tap to connect" - On hover β blue border glows Β· arrow icon fades in
- On tap β immediate
Navigator.pop(deviceId)β no additional confirm step
β Back to README Β· Boot Flow Β» Β· Modules Β»