GithubHelp home page GithubHelp logo

nimrodda / flutter_nsd Goto Github PK

View Code? Open in Web Editor NEW
32.0 3.0 9.0 312 KB

A Flutter plugin that enables Network Service Discovery (mDNS) on various platforms via their native APIs.

License: Apache License 2.0

Kotlin 7.39% Ruby 3.00% Swift 5.70% Objective-C 0.48% Dart 6.49% CMake 6.27% C++ 23.62% C 47.04%
flutter flutter-plugin mdns multicast-dns dns-sd bonjour nsd

flutter_nsd's Introduction

Flutter Network Service Discovery plugin

A Flutter plugin for Network Service Discovery (mDNS) on Android, iOS, MacOS and Windows. The plugin uses the platform's own API when possible.

The plugin currently only supports discovery, but not registry of services.

Install

Add the dependency to pubspec.yaml:

dependencies:
  flutter_nsd: ^1.4.0

Getting Started

Initialize FlutterNsd singleton and listen to the stream:

void init() async {
  final flutterNsd = FlutterNsd();

  flutterNsd.stream.listen((nsdServiceInfo) {
    print('Discovered service name: ${nsdServiceInfo.name}');
    print('Discovered service hostname/IP: ${nsdServiceInfo.hostname}');
    print('Discovered service port: ${nsdServiceInfo.port}');
  }, onError: (e) {
    if (e is NsdError) {
      // Check e.errorCode for the specific error
    }
  });
}

Start discovery when needed. At this point, if any services are discovered, your stream listener will get notified. In case of an error, NsdError is emitted to the stream (Currently it's just a generic error, but in the future, it will be more specific).

void startDiscoveryButton() async {
  await flutterNsd.discoverServices('_http._tcp.');
}

Stop discovery when done. If you don't call this method, discovery will continue until the app process is killed.

void stopDiscoveryButton() async {
  await flutterNsd.stopDiscovery();
}

See the example project for a more detailed Flutter app example.

Note about Android

Minimum Android API version supported is 21.

Android emulator doesn't support Network Service Discovery so you'll have to use a real device.

Note about iOS

This plugin uses NetServiceBrowser and can therefore support iOS version 9+.

On iOS 14+, you need to modify Info.plist file and add two keys:

  • Bonjour Services - this is an array, the first item should be the service you're trying to discover. For example, _http._tcp..
  • Privacy - Local Network Usage Description - this key is for granting the app local network access. The value is the text which will be shown to the user in a permission dialog once you call flutterNsd.discoverServices().

Example:

<key>NSLocalNetworkUsageDescription</key>
<string>Reasoning for the user why you need this permission goes here</string>
<key>NSBonjourServices</key>
<array>
   <string>_http._tcp.</string>
</array>

For more info about network discovery on iOS 14, I suggest you watch this video.

Note that you don't need to worry about modifying Info.plist if you are just testing with a simulator.

The iOS and macOS implementations currently do not return hostAddresses

Note about Windows

Windows does not have native support for MDNS, therefore it is implemented using the https://github.com/mjansson/mdns library which implements MDNS using sockets. The library will return separate results for ipv4 and ipv6.

The current implementation will send MDNS multicast every 10 seconds until stopped.

Due to the native socket calls, any app using this plugin on windows will trigger a dialog from Windows to allow network access on the first launch.

For Windows development you will need Visual Studio 2019 or higher with the C++ workload installed, see https://docs.flutter.dev/desktop#additional-windows-requirements

Testing

On MacOS it's easy to test network service discovery via the following command which will create a mock service:

dns-sd -R TestService _http._tcp . 3000

Then scan for this service using the example app on any of the supported platforms.

License

Copyright 2023 Nimrod Dayan nimroddayan.com

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

flutter_nsd's People

Contributors

deckerst avatar jnstahl avatar julianscheel avatar mdev88 avatar nimrodda avatar pheki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

flutter_nsd's Issues

Unable to obtain IOS local network permissions

I have set "Bonjour services" and "privacy - local network usage description" in info.plist according to the requirements of "note about IOS" in readme in “Flutter-nsd1.2.0", but I still can't obtain local network permissions,But android already does this,Is there anything else I haven't set up on ios?

Bonjour Services: "_connect1._tcp.”

The version number of my ios device is 14.7.1, and the model is iPhone6s Plus

missing permission for some Android versions

Discovery fails on some Android builds due to missing NEARBY_DEVICES permission in the manifest:

An easy workaround is to add this permission into the manifest of the app that uses the package

startDiscoveryFailed every time

Hi!

I am playing with this as a replacement for flutter_mdns_plugin, followed docs and example, and I am getting an startDiscoveryFailed nsd everytime. I am specifically looking for chromecast devices with:

await flutterNsd.discoverServices('_googlecast._tcp');

There is no other native log I can follow. This happens both on Android and iOS, both recent devices ...

Any idea?

Invalid README.md example

It looks like the example in the README.md getting started has been committed mid-changes:

It does not actually handle actual services (the onData argument is unused), but uses onError as if it was onData.

I suppose it was supposed to use onError like in the example

Windows build is failing

Windows build is failing. Not sure if it's only on Github Actions or in general. Haven't had the chance to try it, but just noticed it from @jnstahl 's PR.

Android: Issues on hot-restart

If an app using flutter_nsd is hot-restarted while discovery is active, calling startDiscovery() will fail.
In case timber logging is active it can be seen that a warning is printed, because NSD is already active, but no error is sent back to the app.
This is due to the exception handler in private fun startDiscovery(serviceType: String), which is doing nothing but printing the warning.

To get working discovery after a hot-restart, currently a cycle of discoverServices()->stopDiscovery()->startDiscovery() is required. If the initial error would be notified back to the app it could detect that error condition and only then do an additional stop/start cycle.

Doing only stopDiscovery()->startDiscovery() after a restart is currently not working, because the onDiscoveryStopped handler is called after startDiscovery() only, as at the time of the initial stopDiscovery() call, no method handler is set in the plugin's channel.

Android plugin fails to resolve some of the discovered services

There's two bugs in the plugin:

First, you should not reuse the resolve listener. See https://stackoverflow.com/questions/25815162/listener-already-in-use-service-discovery

Secondly, and this is more problematic, having discovered multiple services, even if resolve listener is not shared, only one of the discovered services will be resolved. See: https://stackoverflow.com/questions/24665342/nsdmanager-doesnt-resolve-multiple-discovered-services

This can be reproduced by creating a couple of services with the same service type,
e.g. in Macos dns-sd -R Foo _http._tcp . 8899 mydevice=1 and dns-sd -R Bar _http._tcp . 8899 mydevice=2

You can see that the problem goes away if you add some delay to before calling nsdManager?.resolveService, but of course that wouldn't be a proper fix.

This is a critical bug, and I would be grateful for fixing it!

Not getting any output from example app even though run shows servers

I'm running the example app on windows and android
https://github.com/Nimrodda/flutter_nsd/tree/master/example

And I can see debug ouput, but nothing is ever posted to the listener

I can see this in my run output
192.168.101.100:5353 : answer osmc.local. A 192.168.101.100
[fe80::a72e:a506:d95d:fae7%65]:5353 : answer _device-info._tcp.local. PTR README._device-info._tcp.local. rclass 0x1 ttl 10 length 9

But flutterNsd.stream.listen never seems to be called

I've tried "_http._tcp." and "_device-info._tcp." which both return this server, but the services array and the UI are never updated to reflect that.

Any help would be appreciated

Some windows hosts cannot resolve hostnames returned by MDNS

the current Windows implementation returns hostnames, such as 'Android-5.local' when provided by the MDNS query results. However some windows hosts do not have the ability to resolve such a hostname and to establish a connection (apparently this ability relies on 3rd party packages such as Bonjour being installed).

Suggested fix:

  • short-term: Windows implementation will always return an IP address string for hostname
  • long-term: the NsdServiceInfo object can be expanded to include:
    • ipv4
    • ipv6
      in addition to hostname and port

Error on executing command 'flutter build windows'

Hi,
I am trying to create a release build of a flutter project with flutter_nsd package

When I build this project for web (flutter build web) seems to be working.
On building for Windows (flutter build windows) I get an error:

used version of package:
flutter_nsd: ^1.4.0

flutter --version
Flutter 3.13.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision e1e47221e8 (28 hours ago) • 2023-08-22 21:43:18 -0700
Engine • revision b20183e040
Tools • Dart 3.1.0 • DevTools 2.25.0

flutter build windows

C:\temp\cnc-client\windows\flutter\ephemeral.plugin_symlinks\flutter_nsd\windows\flutter_nsd_plugin.cpp(104,92): error C2220: the following warning is treated as an error [C:\temp\cnc-client\build\windows\plugins\flutter_nsd\flutter_nsd_plugin.vcxproj]
C:\temp\cnc-client\windows\flutter\ephemeral.plugin_symlinks\flutter_nsd\windows\flutter_nsd_plugin.cpp(104,92): warning C4834: discarding return value of function with 'nodiscard' attribute [C:\temp\cnc-client\build\windows\plugins\flutter_nsd\flutter_nsd_plugin.vcxproj]
C:\temp\cnc-client\windows\flutter\ephemeral.plugin_symlinks\flutter_nsd\windows\flutter_nsd_plugin.cpp(104,120): warning C4834: discarding return value of function with 'nodiscard' attribute [C:\temp\cnc-client\build\windows\plugins\flutter_nsd\flutter_nsd_plugin.vcxproj]
C:\temp\cnc-client\windows\flutter\ephemeral.plugin_symlinks\flutter_nsd\windows\flutter_nsd_plugin.cpp(164,47): warning C4834: discarding return value of function with 'nodiscard' attribute [C:\temp\cnc-client\build\windows\plugins\flutter_nsd\flutter_nsd_plugin.vcxproj]
C:\temp\cnc-client\windows\flutter\ephemeral.plugin_symlinks\flutter_nsd\windows\flutter_nsd_plugin.cpp(164,66): warning C4834: discarding return value of function with 'nodiscard' attribute [C:\temp\cnc-client\build\windows\plugins\flutter_nsd\flutter_nsd_plugin.vcxproj]
Building Windows application... 67,5s
Build process failed.

Workaround:
Edit Windows/CMakelists.txt
Original:
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
to replace with:
target_compile_options(${TARGET} PRIVATE /W4 /wd"4100")

Any plans for Linux support?

Thanks for the library!

My tests so far indicate this is significantly better (faster!) than the multicast_dns package.

Any plans to add support for Linux? Could we fallback to "multicast_dns" for Linux?

stopDiscovery Not working giving below exception

NsdError (message: "stopDiscovery: MulticastLock under-locked nsdMulticastLock", cause: internalError)

NsdError (message: "stopDiscovery: MulticastLock under-locked nsdMulticastLock", cause: internalError)
I/flutter ( 2026): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 2026): │ #0 MethodChannelNsdPlatform.invoke. (package:nsd_platform_interface/src/method_channel_nsd_platform.dart:201:28)
I/flutter ( 2026): │ #1 _rootRunUnary (dart:async/zone.dart:1434:47)
I/flutter ( 2026): │ #2 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
I/flutter ( 2026): │ #3 _FutureListener.handleError (dart:async/future_impl.dart:177:22)
I/flutter ( 2026): │ #4 Future._propagateToListeners.handleError (dart:async/future_impl.dart:778:47)
I/flutter ( 2026): │ #5 Future._propagateToListeners (dart:async/future_impl.dart:799:13)
I/flutter ( 2026): │ #6 Future._completeError (dart:async/future_impl.dart:609:5)
I/flutter ( 2026): │ #7 _completeOnAsyncError (dart:async-patch/async_patch.dart:272:13)
I/flutter ( 2026): │ #8 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart)
I/flutter ( 2026): │ #9
I/flutter ( 2026): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 2026): │ 12:05:02.933 (+0:00:46.781794)
I/flutter ( 2026): ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
I/flutter ( 2026): │ ⛔ ERROR OCCURS NsdError (message: "stopDiscovery: MulticastLock under-locked nsdMulticastLock", cause: internalError)

Services are not discovered on Android

Using this in a flutter app for iOS and Android. While it works as expected on iOS, it does not discover the services on Android. This is on Android 14 (Samsung Galaxy A34 5G)

The Android Gradle plugin supports only Kotlin Gradle plugin version 1.5.20 and higher

Hello

I wanted to try this plugin but I get the following error while compiling:

FAILURE: Build failed with an exception.

* What went wrong:
The Android Gradle plugin supports only Kotlin Gradle plugin version 1.5.20 and higher.
The following dependencies do not satisfy the required version:
project ':flutter_nsd' -> org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 858ms
Exception: Gradle task assembleDebug failed with exit code 1

Example code doesn't show all found services

When discovery gives multiple returned values immediately, the example code skips showing some of the values.

Is the following code in the example intended to work properly?

child: StreamBuilder(
    stream: flutterNsd.stream,
    builder: (context, snapshot) {
        if (snapshot.hasData) {
        services.add(snapshot.data as NsdServiceInfo);

Is the code guaranteed to add every found service to services? In my environment it doesn't seem so. The following code shows more found services in console than what the UI does.

flutterNsd.stream.listen((value) {
      print(value);
}

Add Github Actions config

The plugin should have CI config in place via Github Actions.
In scope:

  • Build all platforms
  • Run lint and formatting checks
  • Tests

Migrate to federated plugin

I was thinking it would be good to migrate the plugin to the federated plugin structure to facilitate contribution. As I understand, this would enable developers to contribute platform implementations in their own repositories, without having to go through PRs. Also, it's how the packages maintained by the Flutter team (such as url_launcher and shared_preferences) are structured now.

The necessary steps are detailed here:

  1. Create platform interface package
  2. Publish to pub.dev
  3. Refactor base package to use platform interface package

I think I'm done with step 1, you can preview it here. I'm not sure how to proceed though, since I can't publish under your name (of course). Let me know if you're interested in doing this. If you don't have the time / resources to do it, I understand, too!

Notify when service is lost

Right now the plugin sends events of services appearing, but no events when they disappear.
According to my brief investigation, Android, iOS and MacOS support this, but Windows which uses the MDNS library requires further investigation.

@jnstahl Do you happen to know if MDNS supports this?

MacOS and iOS not returning any hostAddress

I'm trying to use your library to discover devices on the network, but on iOS and MacOS it doesn't give back any hostAddresses value.

I looked into the code and it doesn't do that at all.

Is that all we can get from those platforms? Or can you get it to work fully on those as well?

stopDiscovery() stops, but generates an error

If I start the discovery and then stop it with stopDiscovery(), I receive a "NsdErrorCode.discoveryStopped" error in the stream listener. Is this by design or am I doing something wrong here?

Thanks!

This is my implementation:

    flutterNsd.stream.listen((nsdServiceInfo) {
      log('Discovered service name: ${nsdServiceInfo.name}');
      log('Discovered service hostname/IP: ${nsdServiceInfo.hostname}');
      log('Discovered service port: ${nsdServiceInfo.port}');
    }, onError: (e) {
      if (e is NsdError) {
        log('NSD ERROR: ${e.errorCode}');  // Why does stopping NSD throws an error? Is this by design?
      } else {
        log('NSD ERROR: $e');
      }
    }, onDone: (){
      log('NSD Done');
    });
  }

Add desktop support macOS

Great, this is exactly what I was looking for 👍 The code seems short and succinct, so that's good. Do you have any plans to support deskop platforms?

Extend NsdServiceInfo to include ipv4 and ipv6

As discussed in #19, currently hostname can be an IP address. It would be better to introduce new fields for storing ipv4 and ipv6. This affects all supported platforms (iOS, MacOS, Android and Windows).

java.lang.IllegalArgumentException: listener not registered

E/AndroidRuntime( 553): FATAL EXCEPTION: NsdManager
E/AndroidRuntime( 553): Process: vip.mymei.remote, PID: 553
E/AndroidRuntime( 553): java.lang.IllegalArgumentException: listener not registered
E/AndroidRuntime( 553): at com.android.internal.util.Preconditions.checkArgument(Preconditions.java:59)
E/AndroidRuntime( 553): at android.net.nsd.NsdManager.getListenerKey(NsdManager.java:496)
E/AndroidRuntime( 553): at android.net.nsd.NsdManager.stopServiceDiscovery(NsdManager.java:636)
E/AndroidRuntime( 553): at com.nimroddayan.flutternsd.FlutterNsdPlugin$discoveryListener$1.onStartDiscoveryFailed(FlutterNsdPlugin.kt:195)
E/AndroidRuntime( 553): at android.net.nsd.NsdManager$ServiceHandler.handleMessage(NsdManager.java:412)
E/AndroidRuntime( 553): at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime( 553): at android.os.Looper.loopOnce(Looper.java:233)
E/AndroidRuntime( 553): at android.os.Looper.loop(Looper.java:334)
E/AndroidRuntime( 553): at android.os.HandlerThread.run(HandlerThread.java:67)
I/Process ( 553): Sending signal. PID: 553 SIG: 9

Stream<NsdServiceInfo> doesn't add service If msdn server hass service txt is added

I'm working with flutter_nsd example and an ESP8266. If I configure my ESP without service txt the example discovers him, but when I add a service txt the example couldn't discover him.
My router has service txt too and can't be discovered by the example.
I think is a Stream declaration problem

My ESP hostname is "lucho", here a print of the stream:
I added a service txt called "endpoint" "/stream"

Pay atention to line: 192.168.0.57:5353 : additional lucho._http._tcp.local. TXT endpoint = /stream
last record in this packet
imagen

I can see the broadcast but service not added

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.