Description
When ADB registers a wireless device as adb-SERIAL (2)._adb-tls-connect._tcp (space before (2) due to mDNS name conflict), Flutter's parser truncates the serial at the first space. The device becomes unreachable and is shown as "Android null (API null) (unsupported)".
Root cause
Flutter parses adb devices -l output with this regex (android_device_discovery.dart):
static final _kDeviceRegex = RegExp(r'^(\S+)\s+(\S+)(.*)');
\S+ stops at the first whitespace. For the line:
adb-ZY22MGW35T-Z3uXXq (2)._adb-tls-connect._tcp device product:vantage_ge ...
The regex parses:
- Group 1 (serial):
adb-ZY22MGW35T-Z3uXXq - truncated, wrong
- Group 2 (state):
(2)._adb-tls-connect._tcp - not a valid state
Flutter then calls adb -s adb-ZY22MGW35T-Z3uXXq - ADB has no transport by that name and returns "device not found".
Steps to reproduce
- Enable Wireless Debugging on Android device.
- Toggle Wireless Debugging off / on (or
adb kill-server && adb start-server) - Android NSD creates a new port while the old mDNS record hasn't expired, triggering ADB's name conflict resolution.
adb devices -l now shows:
adb-ZY22MGW35T-Z3uXXq (2)._adb-tls-connect._tcp device product:...
- Run
flutter devices or flutter run.
Actual behavior
motorola (mobile) • adb-ZY22MGW35T-Z3uXXq • unsupported • Android null (API null)
Error: adb.exe: device 'adb-ZY22MGW35T-Z3uXXq' not found
Expected behavior
Device is detected normally and flutter run succeeds.
Proposed fix
Split on known ADB state keywords instead of \S+:
// Before:
static final _kDeviceRegex = RegExp(r'^(\S+)\s+(\S+)(.*)');
// After:
static final _kDeviceRegex = RegExp(
r'^(.*?)\s+(device|offline|unauthorized|no permissions|bootloader|recovery|sideload|connecting|host)(.*)',
);
(.*?) is lazy - captures the shortest prefix before the first known state keyword, correctly handling serials with spaces. All existing cases (USB serials, emulators, no permissions) continue to work.
A test case is also missing for this scenario and should be added to android_device_discovery_test.dart:
testWithoutContext('parses mDNS serial with space from name conflict suffix', () async {
// adb devices -l output:
// adb-ZY22MGW35T-Z3uXXq (2)._adb-tls-connect._tcp device product:vantage_ge ...
final devices = await androidDevices.pollingGetDevices();
expect(devices.first.id, 'adb-ZY22MGW35T-Z3uXXq (2)._adb-tls-connect._tcp');
expect(devices.first.connectionInterface, DeviceConnectionInterface.wireless);
});
Environment
- Flutter: 3.44.0 (channel stable)
- Dart: 3.12.0
- ADB: 37.0.0-14910828 (latest)
- OS: Windows 11 Pro 10.0.26120
- Device: Motorola, Android 16 (API 36)
- Connection: Wireless Debugging (
_adb-tls-connect._tcp)
Description
When ADB registers a wireless device as
adb-SERIAL (2)._adb-tls-connect._tcp(space before(2)due to mDNS name conflict), Flutter's parser truncates the serial at the first space. The device becomes unreachable and is shown as "Android null (API null) (unsupported)".Root cause
Flutter parses
adb devices -loutput with this regex (android_device_discovery.dart):\S+stops at the first whitespace. For the line:The regex parses:
adb-ZY22MGW35T-Z3uXXq- truncated, wrong(2)._adb-tls-connect._tcp- not a valid stateFlutter then calls
adb -s adb-ZY22MGW35T-Z3uXXq- ADB has no transport by that name and returns "device not found".Steps to reproduce
adb kill-server && adb start-server) - Android NSD creates a new port while the old mDNS record hasn't expired, triggering ADB's name conflict resolution.adb devices -lnow shows:flutter devicesorflutter run.Actual behavior
Expected behavior
Device is detected normally and
flutter runsucceeds.Proposed fix
Split on known ADB state keywords instead of
\S+:(.*?)is lazy - captures the shortest prefix before the first known state keyword, correctly handling serials with spaces. All existing cases (USB serials, emulators,no permissions) continue to work.A test case is also missing for this scenario and should be added to
android_device_discovery_test.dart:Environment
_adb-tls-connect._tcp)