Discover Android service from Windows 10

162 Views Asked by At

I want to be able to resolve a service on my Android phone from my Windows 10 computer. On the desktop I use the library JmDNS :

val SERVICE_TYPE = "_myservice._tcp.local."
val SERVICE_NAME = "MyService"

class SampleListener : ServiceListener {
    override fun serviceAdded(event: ServiceEvent) {
        println("Service added: " + event.info)
    }

    override fun serviceRemoved(event: ServiceEvent) {
        println("Service removed: " + event.info)
    }

    override fun serviceResolved(event: ServiceEvent) {
        println("Service resolved: " + event.info)
    }
}

fun main(args: Array<String>) {
    try {
        // Create a JmDNS instance
        val jmdns = JmDNS.create(InetAddress.getLocalHost())

        // Add a service listener
        jmdns.addServiceListener(SERVICE_TYPE, SampleListener())

        // Wait a bit
        Thread.sleep(30000)
    } catch (e: UnknownHostException) {
        println(e.message)
    } catch (e: IOException) {
        println(e.message)
    }
}

I have a small bit of code to test this code, I just paste it just under jmdns.addServiceListener(/**/) to register and service and check that it is indeed resolved :

ServiceInfo.create(SERVICE_TYPE, SERVICE_NAME, 1234, "path=index.html").also {
    JmDNS.create(InetAddress.getLocalHost()).registerService(it)
}

I get a very satisfying log :

Service added: [ServiceInfoImpl@319915901 name: 'MyService._myservice._tcp.local.' address: '(null):0' status: 'DNS: MY-COMPUTER-NAME.local. state: probing 1 task: null', has NO data empty]
Service resolved: [ServiceInfoImpl@500591471 name: 'MyService._myservice._tcp.local.' address: '/192.168.192.1:1234 /fe80:0:0:0:400f:9ab8:383:6986:1234 ' status: 'DNS: MY-COMPUTER-NAME.local. state: probing 1 task: null' is persistent, has data empty]

Note that 192.168.192.1 is not my computer's address on the local network, I don't know where it comes from. Now that I know my code for resolving services works, I get rid of the service registration and keep only the listener.

On Android I have tried to use NSD (https://developer.android.com/training/connect-devices-wirelessly/nsd) but using it the logs on the desktop app remained empty, so I have imported JmDNS to Android and implemented a small class :

object MdnsService {
    private val TAG = "MDNS_SERVICE"
    val SERVICE_TYPE = "_myservice._tcp.local."
    val SERVICE_NAME = "MyService"
    private lateinit var jmdns: JmDNS

    fun registerService(context: Context, port: Int) {
        // Get IP address
        val wifiManager = context.getSystemService(AppCompatActivity.WIFI_SERVICE) as WifiManager
        val ipAddress: String = Formatter.formatIpAddress(wifiManager.connectionInfo.ipAddress)
        // Create a JmDNS instance
        StrictMode.ThreadPolicy.Builder().permitAll().build().also {
            StrictMode.setThreadPolicy(it)
        }
        jmdns = JmDNS.create(InetAddress.getByName(ipAddress), "MyServiceJMDNS")
        // Register a service
        val serviceInfo = ServiceInfo.create(SERVICE_TYPE, SERVICE_NAME, port, "Kosovo je Srbija")
        try {
            jmdns.registerService(serviceInfo)
            Log.i(TAG, "MDNS service registered")
            Log.d(TAG, serviceInfo.toString())
        } catch (e: IOException) {
            Log.e(TAG, "Failed to register MDNS service", e)
        }
    }

    fun unregisterService(context: Context) {
        jmdns.unregisterAllServices()
        Log.i(TAG, "MDNS service unregistered")
    }
}

I launch my desktop code, then I call the method registerService from my phone, I get this log on the Android side :

I/MDNS_SERVICE: MDNS service registered
D/MDNS_SERVICE: [ServiceInfoImpl@101034026 name: 'MyService._myservice._tcp.local.' address: 'Android.home/[MY-PHONE-IP-ON-LOCAL-NETWORK]:4242 null:4242 ' status: 'DNS: MyServiceJMDNS state: announced task: Renewer(MyServiceJMDNS) state: announced', has data empty]

So the service is registered, but the logs on the desktop app are empty.

I have tested to add this bit of code just before the registration of the service on the Android side just to check if I get my service registration on Android :

jmdns.addServiceListener(SERVICE_TYPE, object: ServiceListener {
    override fun serviceAdded(event: ServiceEvent) {
       println("Service added: " + event.info)
    }

    override fun serviceRemoved(event: ServiceEvent) {
       println("Service removed: " + event.info)
    }

    override fun serviceResolved(event: ServiceEvent) {
       println("Service resolved: " + event.info)
    }
})

And I get this log :

I/System.out: Service added: [ServiceInfoImpl@194352844 name: 'MyService._myservice._tcp.local.' address: '(null):0' status: 'DNS: MyServiceJMDNS state: probing 1 task: null', has NO data empty]
I/System.out: Service resolved: [ServiceInfoImpl@7048469 name: 'MyService._myservice._tcp.local.' address: '/[MY-PHONE-IP-ON-LOCAL-NETWORK]:4242 ' status: 'DNS: MyServiceJMDNS state: probing 1 task: null' is persistent, has data empty]

Side note, I can ping my phone from my comptuter.

It looks like even though my phone and my computer are on the same network, JmDNS seems to fail to "breach through". What am I doing wrong ?

0

There are 0 best solutions below