NsdManager discovery does not work on Android 9
Asked Answered
C

1

5

I have tried for a good time now to get the NsdManager discovery function to work on Android 9. It works on any Android version prior to that without any problems.

For testing purposes I use this simple code snippet and there is a permission for "INTERNET" in the manifest.

var nsdManager = context.getSystemService(Context.NSD_SERVICE) as NsdManager

nsdManager.discoverServices("_https._tcp", NsdManager.PROTOCOL_DNS_SD, object: NsdManager.DiscoveryListener {
    override fun onDiscoveryStarted(serviceType: String?) {
        println("DEBUG: onDiscoveryStarted $serviceType") 
    }
    override fun onDiscoveryStopped(serviceType: String?) {
        println("DEBUG: onDiscoveryStopped $serviceType") 
    }
    override fun onServiceFound(serviceInfo: NsdServiceInfo?) {
        println("DEBUG: onServiceFound $serviceInfo") 
    }
    override fun onServiceLost(serviceInfo: NsdServiceInfo?) {
        println("DEBUG: onServiceLost $serviceInfo") 
    }
    override fun onStartDiscoveryFailed(serviceType: String?, errorCode: Int) {
        println("DEBUG: onStartDiscoveryFailed $serviceType $errorCode") 
    }
    override fun onStopDiscoveryFailed(serviceType: String?, errorCode: Int) {
        println("DEBUG: onStopDiscoveryFailed $serviceType $errorCode") 
    }
})

When this code executes i don't see any debug or error messages in the logs.

With Wireshark I can see the broadcasted mDNS Standard query for "_https._tcp.local" and all corresponding responses from all expected devices. The responses just don't seem to be received on Android because the function "onServiceFound" is never called. In fact no function except "onDiscoveryStared" is ever called.

I have not seen any changes on Android 9 on why this should not be working and any help is gladly appreciated. Maybe i have done something wrong or missed any permission changes in the current Android version.

UPDATE: On an Samsung S9+ with the current Android 9 beta the service discovery works without any problems. On my Pixel 3XL on the other side it does not work.

Cicatrize answered 4/12, 2018 at 14:27 Comment(0)
C
24

Ok I have found a solution for this problem in an old Github issue. Apparently you need to have the wifi multicast permission and need to acquire a MulticastLock to receive multicast messages.

I have yet to find any documentation about this and it seems to not be an specific issue with Android 9 but rather a Google Pixel default setting to disable all listening on multicast packages to preserve battery.

For anyone who comes around this problem and don't want to dive through long issues I have added following code:

AndroidManifest.xml:

<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>

Browser:

WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock multicastLock = wifi.createMulticastLock("multicastLock");
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
.
.
multicastLock.release(); // release after browsing
Cicatrize answered 5/12, 2018 at 11:2 Comment(7)
Ran into same issue, straightforward to resolve following this answer.Klusek
Can confirm this answer solved the problem on Pixel-3a Android 10. The same code was working on non-pixel-3a devices with Android 10 so it seems to be specific to the Pixel series.Laynelayney
Ran into the same issue on a Pixel 2 running Android 8 and this fixed it for meDecorative
Crazy. Can confirm on a Pixel 4a Android 11.Aerostation
I have the same issue on Android 12. The discovery works correctly in all older versions but now on Android 12 it doesn't work. I tried this solution but it doesn't work, only onDiscoveryStared is called. No crash, no errorsFrager
@GiorgioProvenzale any new solution for it?Hearsay
This method worked fine from Android 11 - Android 13, but after the recent update to Android 14, some bonjour services can't be found anymore, so I don't know what the latest changes are for Android 14.Hearsay

© 2022 - 2024 — McMap. All rights reserved.