Question

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
] 
Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top