Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mdns_plugin/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ group 'com.mutablelogic.mdns_plugin'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.3.72'
repositories {
google()
jcenter()
Expand Down Expand Up @@ -40,4 +41,5 @@ android {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:support-annotations:28.0.0'
}
2 changes: 2 additions & 0 deletions mdns_plugin/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
android.useAndroidX=true
android.enableJetifier=true
org.gradle.jvmargs=-Xmx1536M

Original file line number Diff line number Diff line change
@@ -1,63 +1,94 @@
package com.mutablelogic.mdns_plugin

import android.annotation.TargetApi
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.EventChannel.StreamHandler
import io.flutter.plugin.common.EventChannel.EventSink
import io.flutter.plugin.common.PluginRegistry.Registrar
import android.content.Context
import android.net.nsd.NsdManager
import android.net.nsd.NsdServiceInfo
import android.util.Log
import android.app.Activity
import android.os.Build
import androidx.annotation.NonNull
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import java.util.Timer
import kotlin.concurrent.schedule

class MDNSPlugin : MethodCallHandler,StreamHandler {
class MDNSPlugin : FlutterPlugin, MethodCallHandler,StreamHandler, ActivityAware {
var nsdManager: NsdManager? = null
private var channel: MethodChannel? = null
var sink: EventSink? = null
var activity: Activity? = null
var discoveryListener: DiscoveryListener? = null
val services : HashMap<String,NsdServiceInfo> = HashMap<String,NsdServiceInfo>()
private val tag = "MDNSPlugin"

companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
MethodChannel(registrar.messenger(), "mdns_plugin").setMethodCallHandler(MDNSPlugin(registrar))
}
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
Log.d(tag,"onAttachedToEngine")
this.channel = MethodChannel(flutterPluginBinding.binaryMessenger, CHANNEL_NAME)
this.channel?.setMethodCallHandler(this)
EventChannel(flutterPluginBinding.binaryMessenger, "mdns_plugin_delegate").setStreamHandler(this)
}


override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
Log.d(tag,"onDetachedFromEngine")
channel?.setMethodCallHandler(null)
channel = null
}

override fun onDetachedFromActivity() {
Log.d(tag,"onDetachedFromActivity")
}

override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
Log.d(tag,"onReattachedToActivityForConfigChanges")
activity = binding.activity
nsdManager = binding.activity.getSystemService(Context.NSD_SERVICE) as NsdManager
}

fun mapFromServiceInfo(method: String,serviceInfo: NsdServiceInfo?):HashMap<String,Any> {
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
Log.d(tag,"onAttachedToActivity")
activity = binding.activity
nsdManager = binding.activity.getSystemService(Context.NSD_SERVICE) as NsdManager

}

override fun onDetachedFromActivityForConfigChanges() {
Log.d(tag,"onAttachedToActivity")
}
companion object {
const val CHANNEL_NAME = "mdns_plugin"
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
fun mapFromServiceInfo(method: String, serviceInfo: NsdServiceInfo?):HashMap<String,Any> {
val map = HashMap<String, Any>()
map["method"] = method
serviceInfo?.let {
map["name"] = serviceInfo.getServiceName()
map["type"] = serviceInfo.getServiceType().removePrefix(".").removeSuffix(".") + "." // cleanup
map["hostName"] = serviceInfo.getHost()?.getHostName() ?: ""
map["port"] = serviceInfo.getPort()
map["txt"] = serviceInfo.getAttributes()
map["name"] = serviceInfo.serviceName
map["type"] = serviceInfo.serviceType.removePrefix(".").removeSuffix(".") + "." // cleanup
map["hostName"] = serviceInfo.host?.hostName ?: ""
map["port"] = serviceInfo.port
map["txt"] = serviceInfo.attributes

val addr = serviceInfo.getHost()?.getHostAddress()
val addr = serviceInfo.host?.hostAddress
addr?.let {
map["addr"] = listOf(addr,serviceInfo.getPort())
map["addr"] = listOf(addr,serviceInfo.port)
}
}
return map
}
}

constructor(registrar: Registrar) {
nsdManager = registrar.activity().getSystemService(Context.NSD_SERVICE) as NsdManager
activity = registrar.activity()
EventChannel(registrar.messenger(), "mdns_plugin_delegate").setStreamHandler(this)
}

override fun onMethodCall(call: MethodCall, result: Result) {
when (call.method) {
"getPlatformVersion" -> {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
result.success("Android ${Build.VERSION.RELEASE}")
}
"startDiscovery" -> {
startDiscovery(result,call.argument<String>("serviceType") ?: "",call.argument<Boolean>("enableUpdating") ?: false)
Expand Down Expand Up @@ -89,33 +120,34 @@ class MDNSPlugin : MethodCallHandler,StreamHandler {
discoveryListener?.let {
nsdManager?.stopServiceDiscovery(discoveryListener)
}
discoveryListener = DiscoveryListener(this);
discoveryListener = DiscoveryListener(this)
services.clear()
nsdManager?.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, discoveryListener)
result.success(null);
result.success(null)
}

private fun stopDiscovery(result: Result) {
nsdManager?.stopServiceDiscovery(discoveryListener)
discoveryListener = null
services.clear()
result.success(null);
result.success(null)
}

private fun resolveService(result: Result,name: String, resolve: Boolean) {
if(services.containsKey(name)) {
if(resolve) {
nsdManager?.resolveService(services.get(name),ResolveListener(this));
nsdManager?.resolveService(services[name],ResolveListener(this))
} else {
services.remove(name)
}
} else {
Log.w("MDNSPlugin", "resolveService: missing service with name $name")
}
}

}

class ResolveListener(val plugin: MDNSPlugin) : NsdManager.ResolveListener {
class ResolveListener(private val plugin: MDNSPlugin) : NsdManager.ResolveListener {
override fun onServiceResolved(serviceInfo: NsdServiceInfo) {
val serviceMap = MDNSPlugin.mapFromServiceInfo("onServiceResolved",serviceInfo)
plugin.activity?.runOnUiThread(java.lang.Runnable {
Expand All @@ -136,7 +168,7 @@ class ResolveListener(val plugin: MDNSPlugin) : NsdManager.ResolveListener {
}
}

class DiscoveryListener(val plugin: MDNSPlugin) : NsdManager.DiscoveryListener {
class DiscoveryListener(private val plugin: MDNSPlugin) : NsdManager.DiscoveryListener {
override fun onDiscoveryStarted(serviceType: String?) {
plugin.activity?.runOnUiThread(java.lang.Runnable {
plugin.sink?.success(mapOf("method" to "onDiscoveryStarted"))
Expand All @@ -149,7 +181,7 @@ class DiscoveryListener(val plugin: MDNSPlugin) : NsdManager.DiscoveryListener {
}
override fun onServiceFound(serviceInfo: NsdServiceInfo) {
val serviceMap = MDNSPlugin.mapFromServiceInfo("onServiceFound",serviceInfo)
val name = serviceInfo.getServiceName()
val name = serviceInfo.serviceName
name?.let {
plugin.services.put(name,serviceInfo)
}
Expand All @@ -159,7 +191,7 @@ class DiscoveryListener(val plugin: MDNSPlugin) : NsdManager.DiscoveryListener {
}
override fun onServiceLost(serviceInfo: NsdServiceInfo) {
val serviceMap = MDNSPlugin.mapFromServiceInfo("onServiceRemoved",serviceInfo)
plugin.services.remove(serviceInfo.getServiceName())
plugin.services.remove(serviceInfo.serviceName)
plugin.activity?.runOnUiThread(java.lang.Runnable {
plugin.sink?.success(serviceMap)
})
Expand Down
2 changes: 1 addition & 1 deletion mdns_plugin/example/lib/src/models/service_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'package:mdns_plugin/mdns_plugin.dart';
/////////////////////////////////////////////////////////////////////

class ServiceList {
List<MDNSService> _list = List<MDNSService>();
List<MDNSService> _list = <MDNSService>[];

// METHODS ////////////////////////////////////////////////////////

Expand Down
10 changes: 5 additions & 5 deletions mdns_plugin/example/lib/src/pages/service_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ class ServiceList extends StatelessWidget {
title: Text('FOUND CHROMECASTS'),
subtitle: Text(
"The following devices were found on your local network")),
ButtonTheme.bar(
child: ButtonBar(children: <Widget>[
ButtonBar(children: <Widget>[
FlatButton(
child: const Text('RESCAN'),
onPressed: () => appBloc.dispatch(
AppEventDiscovery(AppEventDiscoveryState.Restart)))
]))
onPressed: () => appBloc.dispatch(AppEventDiscovery(
AppEventDiscoveryState.Restart,
)))
]),
]));
});
}
49 changes: 23 additions & 26 deletions mdns_plugin/lib/mdns_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,20 @@ class MDNSService {

// CONSTRUCTORS ///////////////////////////////////////////////////

MDNSService.fromMap(this.map) : assert(map != null);
MDNSService.fromMap(this.map);

// PROPERTIES /////////////////////////////////////////////////////

String get name => map["name"];
String get hostName => map["hostName"];
String get serviceType => map["type"];
int get port => map["port"];
Map get txt => map["txt"];
List<String> get addresses {
String? get name => map["name"];
String? get hostName => map["hostName"];
String? get serviceType => map["type"];
int? get port => map["port"];
Map? get txt => map["txt"];
List<String?> get addresses {
var addresses = map["address"];

if (addresses is List<dynamic>) {
var address = List<String>();
var address = <String?>[];
addresses.forEach((value) {
if (value.length == 2 && value[0] is String) {
address.add(value[0]);
Expand All @@ -71,13 +71,10 @@ class MDNSService {

/// toUTFString decodes a TXT value into a UTF8 string
static String toUTF8String(List<int> bytes) {
if (bytes == null) {
return null;
} else {
return Utf8Codec().decode(bytes);
}
return Utf8Codec().decode(bytes);
}

@override
String toString() {
var parts = "";
if (name != "") {
Expand All @@ -86,15 +83,17 @@ class MDNSService {
if (serviceType != "") {
parts = parts + "serviceType='$serviceType' ";
}
if (hostName != "" && port > 0) {
if (hostName != "" && port! > 0) {
parts = parts + "host='$hostName:$port' ";
}
if (addresses.length > 0) {
if (addresses.isNotEmpty) {
parts = parts + "addresses=$addresses ";
}
txt.forEach((k, v) {
var vstr = toUTF8String(v);
parts = parts + "$k='$vstr' ";
txt?.forEach((k, v) {
if (v != null) {
var vstr = toUTF8String(v);
parts = parts + "$k='$vstr' ";
}
});
return "<MDNSService>{ $parts}";
}
Expand All @@ -105,15 +104,14 @@ class MDNSService {
/// MDNSPlugin is the provider of the mDNS discovery from the local
/// network
class MDNSPlugin {
static const MethodChannel _methodChannel =
const MethodChannel('mdns_plugin');
static const MethodChannel _methodChannel = MethodChannel('mdns_plugin');
static const EventChannel _eventChannel =
const EventChannel('mdns_plugin_delegate');
EventChannel('mdns_plugin_delegate');
final MDNSPluginDelegate delegate;

// CONSTRUCTORS ///////////////////////////////////////////////////

MDNSPlugin(this.delegate) : assert(delegate != null) {
MDNSPlugin(this.delegate) {
_eventChannel.receiveBroadcastStream().listen((args) {
if (args is Map && args.containsKey("method")) {
switch (args["method"]) {
Expand All @@ -125,8 +123,7 @@ class MDNSPlugin {
break;
case "onServiceFound":
var service = MDNSService.fromMap(args);
this._resolveService(service,
resolve: delegate.onServiceFound(service));
_resolveService(service, resolve: delegate.onServiceFound(service));
break;
case "onServiceResolved":
delegate.onServiceResolved(MDNSService.fromMap(args));
Expand All @@ -146,7 +143,7 @@ class MDNSPlugin {

/// platformVersion returns the underlying platform version of the
/// running plugin
static Future<String> get platformVersion async {
static Future<String?> get platformVersion async {
return await _methodChannel.invokeMethod('getPlatformVersion');
}

Expand All @@ -171,7 +168,7 @@ class MDNSPlugin {

Future<void> _resolveService(MDNSService service,
{bool resolve = false}) async {
_methodChannel.invokeMethod(
return _methodChannel.invokeMethod(
'resolveService', {"name": service.name, "resolve": resolve});
}
}
4 changes: 2 additions & 2 deletions mdns_plugin/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ name: mdns_plugin
description:
mDNS Service discovery plugin for iOS & Android which generates
events based on discovery of services on the local network.
version: 1.1.4
version: 2.0.0
author: David Thorpe <djt@mutablelogic.com>
homepage: https://github.com/djthorpe/flutter/

environment:
sdk: ">=2.1.0 <3.0.0"
sdk: ">=2.12.0 <3.0.0"

dependencies:
flutter:
Expand Down