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.
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