diff --git a/mdns_plugin/android/build.gradle b/mdns_plugin/android/build.gradle index a7833e7..e338d68 100644 --- a/mdns_plugin/android/build.gradle +++ b/mdns_plugin/android/build.gradle @@ -2,6 +2,7 @@ group 'com.mutablelogic.mdns_plugin' version '1.0-SNAPSHOT' buildscript { + ext.kotlin_version = '1.3.72' repositories { google() jcenter() @@ -40,4 +41,5 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:support-annotations:28.0.0' } diff --git a/mdns_plugin/android/gradle.properties b/mdns_plugin/android/gradle.properties index 2bd6f4f..4c58a6b 100644 --- a/mdns_plugin/android/gradle.properties +++ b/mdns_plugin/android/gradle.properties @@ -1,2 +1,4 @@ +android.useAndroidX=true +android.enableJetifier=true org.gradle.jvmargs=-Xmx1536M diff --git a/mdns_plugin/android/src/main/kotlin/com/mutablelogic/mdns_plugin/MDNSPlugin.kt b/mdns_plugin/android/src/main/kotlin/com/mutablelogic/mdns_plugin/MDNSPlugin.kt index 471e84b..930e3d7 100644 --- a/mdns_plugin/android/src/main/kotlin/com/mutablelogic/mdns_plugin/MDNSPlugin.kt +++ b/mdns_plugin/android/src/main/kotlin/com/mutablelogic/mdns_plugin/MDNSPlugin.kt @@ -1,5 +1,6 @@ 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 @@ -7,57 +8,87 @@ 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 = HashMap() + 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 { + 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 { val map = HashMap() 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("serviceType") ?: "",call.argument("enableUpdating") ?: false) @@ -89,23 +120,23 @@ 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) } @@ -113,9 +144,10 @@ class MDNSPlugin : MethodCallHandler,StreamHandler { 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 { @@ -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")) @@ -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) } @@ -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) }) diff --git a/mdns_plugin/example/lib/src/models/service_list.dart b/mdns_plugin/example/lib/src/models/service_list.dart index 0e32a3d..95a6728 100644 --- a/mdns_plugin/example/lib/src/models/service_list.dart +++ b/mdns_plugin/example/lib/src/models/service_list.dart @@ -12,7 +12,7 @@ import 'package:mdns_plugin/mdns_plugin.dart'; ///////////////////////////////////////////////////////////////////// class ServiceList { - List _list = List(); + List _list = []; // METHODS //////////////////////////////////////////////////////// diff --git a/mdns_plugin/example/lib/src/pages/service_list.dart b/mdns_plugin/example/lib/src/pages/service_list.dart index a8177da..b292637 100644 --- a/mdns_plugin/example/lib/src/pages/service_list.dart +++ b/mdns_plugin/example/lib/src/pages/service_list.dart @@ -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: [ + ButtonBar(children: [ FlatButton( child: const Text('RESCAN'), - onPressed: () => appBloc.dispatch( - AppEventDiscovery(AppEventDiscoveryState.Restart))) - ])) + onPressed: () => appBloc.dispatch(AppEventDiscovery( + AppEventDiscoveryState.Restart, + ))) + ]), ])); }); } diff --git a/mdns_plugin/lib/mdns_plugin.dart b/mdns_plugin/lib/mdns_plugin.dart index 45d40fd..ea726e4 100644 --- a/mdns_plugin/lib/mdns_plugin.dart +++ b/mdns_plugin/lib/mdns_plugin.dart @@ -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 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 get addresses { var addresses = map["address"]; if (addresses is List) { - var address = List(); + var address = []; addresses.forEach((value) { if (value.length == 2 && value[0] is String) { address.add(value[0]); @@ -71,13 +71,10 @@ class MDNSService { /// toUTFString decodes a TXT value into a UTF8 string static String toUTF8String(List bytes) { - if (bytes == null) { - return null; - } else { - return Utf8Codec().decode(bytes); - } + return Utf8Codec().decode(bytes); } + @override String toString() { var parts = ""; if (name != "") { @@ -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 "{ $parts}"; } @@ -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"]) { @@ -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)); @@ -146,7 +143,7 @@ class MDNSPlugin { /// platformVersion returns the underlying platform version of the /// running plugin - static Future get platformVersion async { + static Future get platformVersion async { return await _methodChannel.invokeMethod('getPlatformVersion'); } @@ -171,7 +168,7 @@ class MDNSPlugin { Future _resolveService(MDNSService service, {bool resolve = false}) async { - _methodChannel.invokeMethod( + return _methodChannel.invokeMethod( 'resolveService', {"name": service.name, "resolve": resolve}); } } diff --git a/mdns_plugin/pubspec.yaml b/mdns_plugin/pubspec.yaml index 06bfacc..df4bc61 100644 --- a/mdns_plugin/pubspec.yaml +++ b/mdns_plugin/pubspec.yaml @@ -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 homepage: https://github.com/djthorpe/flutter/ environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: