native_mdns_scanner 1.5.0
native_mdns_scanner: ^1.5.0 copied to clipboard
Dart FFI bindings for macOS mDNS/Bonjour services. Provides native access to multicast DNS functionality on macOS.
example/native_mdns_scanner_example.dart
import 'package:native_mdns_scanner/native_mdns_scanner.dart';
void main() async {
final mdnsFfi = NativeMdnsScanner();
final foundDevices = <DeviceInfo>[];
try {
print('π Basic mDNS scanning example\n');
print('π± Scanning for Chromecast devices...');
mdnsFfi.startScanJson('_googlecast._tcp', (json) {
if (json['type'] == 'device') {
foundDevices.add(DeviceInfo(
name: json['name'] ?? '',
ip: json['ip'] ?? '',
port: json['port'] ?? 0,
serviceType: json['type_name'] ?? '',
txtRecords: Map<String, String>.from(json['txt'] ?? {}),
));
} else if (json['type'] == 'error') {
print('β Native error: \'${json['message']}\'');
}
}, debug: 2);
// Wait for 10 seconds
await Future.delayed(Duration(seconds: 10));
mdnsFfi.stopScan();
print('Found \\${foundDevices.length} Chromecast devices:');
for (final device in foundDevices) {
print(' β’ \\${device.name} at \\${device.ip}:\\${device.port}');
if (device.txtRecords.isNotEmpty) {
print(' TXT records: \\${device.txtRecords}');
}
}
print('\n' + '=' * 50);
// Example 2: Scan multiple service types
print('π― Scanning multiple service types simultaneously...');
foundDevices.clear();
final multiTypes = ['_googlecast._tcp', '_airplay._tcp', '_raop._tcp'];
for (final type in multiTypes) {
mdnsFfi.startScanJson(type, (json) {
if (json['type'] == 'device') {
foundDevices.add(DeviceInfo(
name: json['name'] ?? '',
ip: json['ip'] ?? '',
port: json['port'] ?? 0,
serviceType: json['type_name'] ?? '',
txtRecords: Map<String, String>.from(json['txt'] ?? {}),
));
} else if (json['type'] == 'error') {
print('β Native error: \\${json['message']}');
}
}, debug: 2);
await Future.delayed(Duration(milliseconds: 200));
}
await Future.delayed(Duration(seconds: 15));
mdnsFfi.stopScan();
print('\nFound \\${foundDevices.length} devices total:');
final devicesByType = <String, List<DeviceInfo>>{};
for (final device in foundDevices) {
devicesByType.putIfAbsent(device.serviceType, () => []).add(device);
}
for (final serviceType in devicesByType.keys) {
final typeDevices = devicesByType[serviceType]!;
print('\n\\${serviceType} (\\${typeDevices.length} devices):');
for (final device in typeDevices) {
print(' β’ \\${device.name} (\\${device.ip}:\\${device.port})');
}
}
print('\n' + '=' * 50);
// Example 3: Periodic scanning
print('π Periodic scanning example...');
print('Sending queries every 3 seconds for 12 seconds total\n');
foundDevices.clear();
await mdnsFfi.startPeriodicScanJsonWithDone(
'_googlecast._tcp',
(json) {
if (json['type'] == 'device') {
foundDevices.add(DeviceInfo(
name: json['name'] ?? '',
ip: json['ip'] ?? '',
port: json['port'] ?? 0,
serviceType: json['type_name'] ?? '',
txtRecords: Map<String, String>.from(json['txt'] ?? {}),
queryNumber: json['queryNumber'] ?? 0,
));
} else if (json['type'] == 'error') {
print('β Native error: \\${json['message']}');
}
},
queryIntervalMs: 3000, // ζ― 3 η§ζ₯θ©’δΈζ¬‘
totalDurationMs: 12000, // ε
±ε·θ‘ 12 η§
debug: 2,
);
print('\nPeriodic scan results:');
for (final device in foundDevices) {
print(
' β’ \\${device.name} found in query #\\${device.queryNumber} at \\${TimingAnalyzer.formatTime(device.foundAt)}');
}
// Show timing analysis
if (foundDevices.isNotEmpty) {
print('\nπ Timing Analysis:');
TimingAnalyzer.analyzeTimings(foundDevices);
}
} catch (e) {
print('β Error during scanning: $e');
} finally {
print('\nπ§Ή Cleaning up...');
mdnsFfi.dispose();
print('β
Done!');
}
}