flutter_local_device_discovery 2.0.0
flutter_local_device_discovery: ^2.0.0 copied to clipboard
Local-network device and service discovery for Flutter using native mDNS/DNS-SD, Bonjour, SSDP, WS-Discovery, and secure UPnP metadata on Android, iOS, macOS, Windows, and Linux.
flutter_local_device_discovery #
Discover, resolve, classify, and monitor devices and services on the local network from Flutter. Version 2.0 brings native SSDP & WS-Discovery engines, native Linux D-Bus Avahi desktop support, network topology graph mapping, native Wi-Fi connection metadata, native ICMP pinging, permission querying, expanded 500+ OUI manufacturer resolution, and specialized smart home decoders (Matter, HomeKit HAP, Google Cast, AirPlay, Spotify Connect, Sonos, MQTT, Home Assistant, IPP).
Features #
- Native Android NSD, Apple Network framework, Windows DNS-SD, and Linux D-Bus Avahi service discovery
- Native SSDP and WS-Discovery multicast engines on Android, iOS, macOS, Windows, and Linux
- Network topology graph builder (
buildTopology()) with automatic gateway detection and hop-count analysis - Native Wi-Fi & network metadata inspection (
getNetworkInfo()) for SSID, BSSID, RSSI, band, channel, speed, and gateway - Native ICMP reachability probing (
probeIcmp()) - Discovery permission checking and requesting (
checkPermissions()) - Offline IEEE OUI manufacturer resolution for 500+ vendor prefixes
- Smart home & IoT protocol decoders (Matter/Thread, HomeKit HAP, Google Cast, AirPlay, Spotify, Sonos, MQTT, Home Assistant, IPP)
- Modular
DiscoveryProtocolAdapterAPI for integrating custom discovery engines - Multicast health diagnostics to detect router multicast drops / IGMP snooping
- Secure, bounded UPnP device-description retrieval with anti-SSRF protections
- Cross-protocol deduplication by UDN, hostname, address, and service identity
- Full JSON serialization (
toJson()/fromJson()) across all models
Platform support #
| Platform | Minimum | Discovery support |
|---|---|---|
| Android | API 21 | Native NSD, native SSDP/UPnP, native WS-Discovery, Wi-Fi info, gateway detection, ARP cache |
| iOS | 13.0 | Network framework, native SSDP/UPnP, native WS-Discovery, Wi-Fi info, gateway detection |
| macOS | 10.15 | Network framework, native SSDP/UPnP, native WS-Discovery, CoreWLAN Wi-Fi info, gateway detection |
| Windows | Flutter-supported versions | Native DNS-SD/mDNS, native SSDP/UPnP, native WS-Discovery, WLAN API info, gateway detection |
| Linux | Flutter-supported versions | Native D-Bus Avahi mDNS/DNS-SD, native SSDP/WS-Discovery, NetworkManager info, /proc/net/route gateway |
| Web | — | API compiles and reports unsupported; browsers cannot open the required multicast sockets |
The package requires Dart 3.5 or later and Flutter 3.24 or later.
Installation #
Add the package to your application:
dependencies:
flutter_local_device_discovery: ^2.0.0
Then run flutter pub get.
Snapshot discovery #
discover starts a bounded session, waits for the configured duration, returns its normalized snapshot, and releases the session resources.
import 'package:flutter_local_device_discovery/flutter_local_device_discovery.dart';
final discovery = FlutterLocalDeviceDiscovery();
final snapshot = await discovery.discover(
const LocalDiscoveryRequest(
duration: Duration(seconds: 8),
protocols: {
LocalDiscoveryProtocol.mdns,
LocalDiscoveryProtocol.dnsSd,
LocalDiscoveryProtocol.ssdp,
LocalDiscoveryProtocol.upnp,
},
serviceTypes: {
'_http._tcp',
'_ipp._tcp',
'_googlecast._tcp',
},
ssdpSearchTargets: {'ssdp:all'},
fetchUpnpDescriptions: true,
),
);
for (final device in snapshot.devices) {
print('${device.displayName}: ${device.addresses}');
}
UPnP metadata retrieval is opt-in. Set fetchUpnpDescriptions to true and include either ssdp or upnp in protocols.
Continuous discovery #
Keep the event subscription and session, then cancel and stop both when the owning component is disposed.
final session = await discovery.start(
const LocalDiscoveryRequest(
mode: LocalDiscoveryMode.continuous,
protocols: {
LocalDiscoveryProtocol.mdns,
LocalDiscoveryProtocol.dnsSd,
LocalDiscoveryProtocol.ssdp,
},
serviceTypes: {'_http._tcp'},
ssdpSearchTargets: {'ssdp:all'},
),
);
final subscription = session.events.listen((event) {
switch (event) {
case LocalDeviceAdded(:final device):
print('Added: ${device.displayName}');
case LocalDeviceUpdated(:final device):
print('Updated: ${device.displayName}');
case LocalDeviceRemoved(:final device):
print('Removed: ${device.displayName}');
case LocalDiscoveryWarning(:final message):
print('Warning: $message');
case LocalDiscoveryFailure(:final error):
print('Failure: $error');
case _:
break;
}
});
// When discovery is no longer needed:
await subscription.cancel();
await session.stop();
Sessions also support pause(), resume(), and snapshot().
Capabilities and readiness #
Check support before presenting protocol-specific controls, then check whether a concrete request can start:
final capabilities = await discovery.getCapabilities();
print(capabilities.supportedProtocols);
final request = const LocalDiscoveryRequest(
protocols: {LocalDiscoveryProtocol.ssdp},
ssdpSearchTargets: {'ssdp:all'},
);
final readiness = await discovery.checkReadiness(request);
if (!readiness.canStart) {
print('Requirements: ${readiness.requirements}');
}
Classification evidence and UPnP identity #
Classification is an inference from observable service and device metadata. Applications can inspect the supporting evidence instead of treating a classification as authoritative.
for (final device in snapshot.devices) {
print('Type: ${device.type}');
print('UPnP UDN: ${device.identity.upnpUdn}');
for (final evidence in device.capabilityEvidence) {
print('${evidence.capability}: ${evidence.source}');
}
}
Platform configuration #
Android #
The Android implementation declares these permissions and they are merged into the consuming application manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
iOS #
Add a purpose string and every Bonjour service type your application browses to ios/Runner/Info.plist:
<key>NSLocalNetworkUsageDescription</key>
<string>This app discovers devices and services available on your local network.</string>
<key>NSBonjourServices</key>
<array>
<string>_http._tcp</string>
<string>_ipp._tcp</string>
</array>
Only declare service types the application actually uses.
macOS #
Add the same NSLocalNetworkUsageDescription and NSBonjourServices entries to macos/Runner/Info.plist. Sandboxed applications also need client and server networking in both debug/profile and release entitlements:
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
Enabling Local Network Access (macOS & iOS)
If you encounter Network.NWError error -65555 - NoAuth or no devices appear, verify that Local Network permissions are enabled:
On macOS:
- Open System Settings ( > System Settings).
- Click Privacy & Security in the sidebar.
- Scroll down and click Local Network.
- Find
device_discovery(orRunner/ your terminal or IDE if running in debug mode) and toggle the switch to ON (Enabled). - Re-open or re-run the app.
On iOS:
- Open the Settings app on the iPhone/iPad.
- Scroll down to
Device Discovery(or Privacy & Security > Local Network). - Ensure the Local Network switch is turned ON.
Windows #
Windows Firewall or enterprise policy can filter multicast UDP. Test on the intended network profile; the plugin does not create firewall exceptions.
UPnP metadata security #
UPnP descriptions are untrusted network input. The default MetadataSecurityPolicy:
- permits private and link-local targets only
- blocks public and loopback targets
- validates and pins resolved connection addresses
- validates every redirect target
- limits redirects, response size, request time, and XML depth
- rejects XML document types and entity declarations
Relax allowExternalAddresses or allowLoopbackAddresses only when the application explicitly trusts those targets.
Important behavior #
- Discovery is not authentication, pairing, or a guaranteed network inventory.
- Guest Wi-Fi, client isolation, VPNs, firewalls, and enterprise multicast policy can hide devices.
- A missing response does not prove that a device is offline.
- Service and device metadata can be malformed or intentionally deceptive.
- Neighbor-table inspection, reachability probing, and safe port probing are fully implemented and supported in v1.0.0.
Example #
The included example application is a v0.2 review console with protocol controls, live device/service events, UPnP metadata, capability evidence, readiness, and diagnostics.
Additional documentation #
License #
MIT. See LICENSE.