JmDNS: Can't resolve service
Asked Answered
F

2

9

I'm trying to implement JmDNS discovery for communication between an Android app and a desktop application. I have followed the following tutorial: http://home.heeere.com/tech-androidjmdns.html

The Android app registers a service and the desktop application adds a listener for the service. I've got it working perfectly fine with three out of four of my devices, but with the fourth one (a Samsung Galaxy Tab 10.1 PT7500 running Android 3.2) I can't resolve the service. My handler receives the serviceAdded event, but no serviceResolved event. I have also tried calling jmdns.requestServiceInfo and jmdns.getServiceInfo, but the former does nothing and the latter times out and returns null.

The jmdns-browser, however, is able to resolve the service just fine, so it's not the device. There is no firewall on either of the devices. The service always uses an IPv4 address.

Does anybody have an idea what could cause this problem?

Code for starting the service:

jmdns = JmDNS.create(wifiAddress);

ServiceInfo serviceInfo = ServiceInfo.create(Constants.SERVICE_TYPE, 
    Constants.SERVICE_NAME, Constants.ZEROCONF_PORT, "my service");

HashMap<String, String> deviceInfoMap = new HashMap<String, String>();
deviceInfoMap.put(Constants.KEY_DEVICE_NAME, getDeviceName());
deviceInfoMap.put(Constants.KEY_DEVICE_ID, getDeviceId());
// ...
serviceInfo.setText(deviceInfoMap);

jmdns.registerService(serviceInfo);

Code for the client / listener:

jmdns = JmDNS.create();
jmdns.addServiceListener(Constants.SERVICE_TYPE, serviceListener = new ServiceListener() {
    @Override
    public void serviceResolved(ServiceEvent event) {
        System.out.println("Service resolved: " + event.getName() + 
            " of type " +    event.getType());
    }

    @Override
    public void serviceRemoved(ServiceEvent event) {
        System.out.println("Service removed: " + event.getName() + 
            " of type " + event.getType());
    }

    @Override
    public void serviceAdded(ServiceEvent event) {
        System.out.println("Service added: " + event.getName() + 
            " of type " + event.getType());
        ServiceInfo info = jmdns.getServiceInfo(event.getType(), event.getName());
        System.out.println("Service info: " + info); // --> null
    }
});

Output:

Service added: my service @ GT-P7500 of type _mytype._tcp.local.
Service info: null
Service added: my service @ Galaxy Nexus of type _mytype._tcp.local.
Service info: [ServiceInfoImpl@183779345 
    name: 'my service @ Galaxy Nexus ._mytype._tcp.local.' 
    address: '/192.168.1.154:4242 ' status: 'DNS: myhost.local. 
    state: probing 1 task: null', has data
    deviceName: Galaxy Nexus
    deviceId: <id>
    displayDensity: XHDPI
] 
Fatherland answered 15/1, 2013 at 14:59 Comment(2)
Mybe you can show you code here.Dorella
Realize this is an old thread, but I wanted to add a word of caution on JmDNS. It worked fine for us in testing, but in the wild it's been a complete nightmare, exhausting heap and native memory with massive numbers of threads. I filed a few issues and haven't heard anything.Capitalist
F
8

Checking out the latest source code version from the github repository did the trick. Discovering the service now works just fine on all devices. (Note: I was using JmDNS version 3.4.1 which I had downloaded from sourceforge before)

Having skimmed through the SVN history, there seem to be a couple of commits related to problems with resolving services since the 3.4.1 release.

Edit: Replaced svn with github repository since jmdns has moved there.

Fatherland answered 18/1, 2013 at 15:49 Comment(4)
I get: 04-29 15:55:21.367 1169-4019/? W/DnsProxyListener﹕ GetHostByAddrHandler: Error writing DNS result to client 04-29 15:55:21.367 1169-4019/? W/SocketClient﹕ write error (Broken pipe), when I try to resolve my service. Any idea what it means?Cantor
@Algorithm and Blues: The latest source code from the SVN repository seems to be the same version (3.4.1) as in the sourceforge... Am I missing something?Nickelsen
@Nickelsen It has been a while, but I think the repository had a couple of additional commits while the version number remained at 3.4.1.Fatherland
@Nickelsen Just checked and saw that the zip file on the download page has been updated since my original post too. So they might actually be identical - I suggest you try the zip download first and then the svn trunk if you're still having problems.Fatherland
P
1

Use JmDNS.create(InetAddress addr, String name) instead of JmDNS.create(). In more recent versions of Android, JmDNS needs to know more about the local device and the network interface it is listening on.

JmDNS jmdns; // somewhere global

// In a background thread 
public void buildJmDNS() {
    InetAddress addr = InetAddress.getLocalHost();
    String hostname = InetAddress.getByName(addr.getHostName()).toString();
    try {
        jmdns = JmDNS.create(addr, hostname); // throws IOException
    } catch (IOException e) {
       e.printStackTrace(); // handle this if you want
    }
}

I had the same issue you are experiencing and this solved it for me. I have tried to find the example I had found that shows why this is necessary, but I cannot.

Periotic answered 18/1, 2013 at 15:27 Comment(1)
I already did pass the InetAddress on the Android side, so I don't think this solution applies for me.Fatherland

© 2022 - 2024 — McMap. All rights reserved.