discoverFirebaseEmulatorHost static method
Discovers the host machine's IP address for Firebase emulator
Implementation
static Future<String?> discoverFirebaseEmulatorHost({int port = 5001}) async {
if (kIsWeb) {
return '127.0.0.1'; // Web always uses localhost
}
logd('Starting Firebase emulator host discovery on port $port...');
// Try cached address first (if available)
final cachedAddress = await _getCachedEmulatorAddress();
if (cachedAddress != null) {
logd('Testing cached emulator address: $cachedAddress');
if (await _testConnection(cachedAddress, port)) {
logd('Cached Firebase emulator address still valid: $cachedAddress');
return cachedAddress;
} else {
logd('Cached address no longer valid, clearing cache');
await _clearCachedEmulatorAddress();
}
}
// Test localhost first (might work for some setups)
if (await _testConnection('127.0.0.1', port)) {
logd('Firebase emulator found at localhost');
await _saveCachedEmulatorAddress('127.0.0.1');
return '127.0.0.1';
}
// Get device IP addresses to determine which subnets to scan
final deviceIps = await getDeviceIpAddresses();
final subnetsToScan = <String>{};
// Extract subnets from device IPs
for (final deviceIp in deviceIps) {
final subnet = _getSubnetFromIp(deviceIp);
if (subnet.isNotEmpty) {
subnetsToScan.add(subnet);
logd('Will scan subnet $subnet (from device IP: $deviceIp)');
}
}
// If no device IPs found, fall back to common ranges
if (subnetsToScan.isEmpty) {
logd('No device IPs found, using common network ranges');
subnetsToScan.addAll([
'192.168.1.', // Common home networks
'172.20.10.', // iOS hotspot range
'192.168.0.', // Common router default
'10.0.0.', // Some corporate networks
'10.0.1.', // Alternative corporate setup
'172.16.0.', // Docker/VPN networks
'192.168.43.', // Android hotspot range
]);
}
// Test each subnet with priority IPs first
for (final range in subnetsToScan) {
// Test common host IPs first (router gateway, common static IPs)
final priorityIPs = [1, 100, 101, 102, 2, 10, 20, 50];
// Test priority IPs in parallel
final priorityFutures = priorityIPs.map((ip) async {
final address = '$range$ip';
if (await _testConnection(address, port)) {
return address;
}
return null;
}).toList();
final priorityResults = await Future.wait(priorityFutures);
for (final result in priorityResults) {
if (result != null) {
logd('Firebase emulator found at: $result');
await _saveCachedEmulatorAddress(result);
return result;
}
}
// If priority IPs don't work, scan the full range in parallel batches
const batchSize = 20; // Test 20 IPs at a time
for (int batchStart = 2; batchStart <= 254; batchStart += batchSize) {
final batchEnd = (batchStart + batchSize - 1).clamp(2, 254);
final batchFutures = <Future<String?>>[];
for (int i = batchStart; i <= batchEnd; i++) {
if (priorityIPs.contains(i)) continue; // Skip already tested IPs
final address = '$range$i';
batchFutures.add(_testConnection(address, port).then((success) {
return success ? address : null;
}));
}
final batchResults = await Future.wait(batchFutures);
for (final result in batchResults) {
if (result != null) {
logd('Firebase emulator found at: $result');
await _saveCachedEmulatorAddress(result);
return result;
}
}
}
}
logw('Firebase emulator host not found');
return null;
}