1

I am making my first PhoneGap app for Android and it needs mDNS resolution. As ".local" addresses are not resolved on Android (before v4.1), I have used a ZeroConf library with JmDNS.jar file. I have taken reference for plugin from this GitHub repository, you might wanna have a look.

ZeroConf.java

public PluginResult execute(String action, JSONArray args, String callbackId) {
    this.callback = callbackId;

    if (action.equals("watch")) {
        String type = args.optString(0);
        if (type != null) {
            watch(type);
        } else {
            return new PluginResult(PluginResult.Status.ERROR, "Service type not specified");
        }
    } else if (action.equals("unwatch")) {
        String type = args.optString(0);
        if (type != null) {
            unwatch(type);
        } else {
            return new PluginResult(PluginResult.Status.ERROR, "Service type not specified");
        }
    } else if (action.equals("register")) {
        JSONObject obj = args.optJSONObject(0);
        if (obj != null) {
            String type = obj.optString("type");
            String name = obj.optString("name");
            int port = obj.optInt("port");
            String text = obj.optString("text");
            if(type == null) {
                return new PluginResult(PluginResult.Status.ERROR, "Missing required service info");
            }
            register(type, name, port, text);
        } else {
            return new PluginResult(PluginResult.Status.ERROR, "Missing required service info");
        }

    } else if (action.equals("close")) { 
        if(jmdns != null) {
            try {
                jmdns.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }  else if (action.equals("unregister")) {
        if(jmdns != null) {
            jmdns.unregisterAllServices();
        }

    } else {
        Log.e("ZeroConf", "Invalid action: " + action);
        return new PluginResult(PluginResult.Status.INVALID_ACTION);
    }
    PluginResult result = new PluginResult(Status.NO_RESULT);
    result.setKeepCallback(true);
    return result;
}

private void watch(String type) {
    if(jmdns == null) {
        setupWatcher();
    }
    Log.d("ZeroConf", "Watch " + type);
    Log.d("ZeroConf", "Name: " + jmdns.getName() + " host: " + jmdns.getHostName());
    jmdns.addServiceListener(type, listener);
}
private void unwatch(String type) {
    if(jmdns == null) {
        return;
    }
    jmdns.removeServiceListener(type, listener);
}

private void register (String type, String name, int port, String text) {
    if(name == null) {
        name = "";
    }

    if(text == null) {
        text = "";
    }

     try {
         ServiceInfo service = ServiceInfo.create(type, name, port, text);
        jmdns.registerService(service);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void setupWatcher() {
    Log.d("ZeroConf", "Setup watcher");
     WifiManager wifi = (WifiManager) this.cordova.getActivity().getSystemService(android.content.Context.WIFI_SERVICE);
    lock = wifi.createMulticastLock("ZeroConfPluginLock");
    lock.setReferenceCounted(true);
    lock.acquire();
    try {
        jmdns = JmDNS.create();
        listener = new ServiceListener() {

            public void serviceResolved(ServiceEvent ev) {
                Log.d("ZeroConf", "Resolved");

                sendCallback("added", ev.getInfo());
            }

            public void serviceRemoved(ServiceEvent ev) {
                Log.d("ZeroConf", "Removed");

                sendCallback("removed", ev.getInfo());
            }

            public void serviceAdded(ServiceEvent event) {
                Log.d("ZeroConf", "Added");

                // Force serviceResolved to be called again
                jmdns.requestServiceInfo(event.getType(), event.getName(), 1);
            }
        };

    } catch (IOException e) {
        e.printStackTrace();
        return;
    }
}

public void sendCallback(String action, ServiceInfo info) {
    JSONObject status = new JSONObject();
    try {
        status.put("action", action);
        status.put("service", jsonifyService(info));
        Log.d("ZeroConf", "Sending result: " + status.toString());

        PluginResult result = new PluginResult(PluginResult.Status.OK, status);
        result.setKeepCallback(true);
        this.success(result, this.callback);

    } catch (JSONException e) {

        e.printStackTrace();
    }


}


public static JSONObject jsonifyService(ServiceInfo info) {
    JSONObject obj = new JSONObject();
    try {
        obj.put("application", info.getApplication());
        obj.put("domain", info.getDomain());
        obj.put("port", info.getPort());
        obj.put("name", info.getName());
        obj.put("server", info.getServer());
        obj.put("description", info.getNiceTextString());
        obj.put("protocol", info.getProtocol());
        obj.put("qualifiedname", info.getQualifiedName());
        obj.put("type", info.getType());

        JSONArray addresses = new JSONArray();
        String[] add = info.getHostAddresses();
        for(int i = 0; i < add.length; i++) {
            addresses.put(add[i]);
        }
        obj.put("addresses", addresses);
        JSONArray urls = new JSONArray();

        String[] url = info.getURLs();
        for(int i = 0; i < url.length; i++) {
            urls.put(url[i]);
        }
        obj.put("urls", urls);

    } catch (JSONException e) {
        e.printStackTrace();
        return null;
    }

    return obj;

}

ZeroConf.js

var ZeroConf = {
watch: function(type, callback) {
    return cordova.exec(function(result) {
        if(callback) {
            callback(result);
        }

    }, ZeroConf.fail, "ZeroConf", "watch", [type]);
},
unwatch: function(type) {
    return cordova.exec(null, ZeroConf.fail, "ZeroConf", "unwatch", [type]);
},
close: function() {
    return cordova.exec(null, ZeroConf.fail, "ZeroConf", "close", [])
},
register: function(type, name, port, text) {
    if(!type) {
        console.error("'type' is a required field");
        return;
    }
    return cordova.exec(null, ZeroConf.fail, "ZeroConf", "register", [type, name, port, text]);
}
unregister: function() {
    return cordova.exec(null, ZeroConf.fail, "ZeroConf", "unregister", [])
},
fail: function (o) {
    console.error("Error " + JSON.stringify(o));
}
}

config.xml

<plugins>
    <plugin name="ZeroConf" value="com.triggertrap.ZeroConf"/>
</plugins>

NOW MY QUESTION:

I want to call a fixed URL, for example, http://foo.local/abc/ in index.html page and it should resolve to the local IP Address. How do I achieve this? I know it has to be done using JavaScript, but how to go about it? I have searched many many articles and reached till here. I would appreciate if you could guide me a little further.

Rishi Jasapara
  • 638
  • 9
  • 33
  • could you achieve this.. i am refering to this question- http://stackoverflow.com/questions/40235229/unable-to-communicate-to-device-with-local-domain-using-android-corova-zerocon can you help me ? – Daga Arihant Feb 07 '17 at 12:54

1 Answers1

2

Somewhere after you receive the 'device ready' event you can register to watch for services advertised over bonjour:

ZeroConf.watch("_http._tcp.local.", function (service) { // do something with the service }

However, using the ZeroConf plugin is not enough as you also need the server that serves content at foo.local to advertise its HTTP service over bonjour. If you use a node.js server you can use this module.

Vlad Stirbu
  • 1,732
  • 2
  • 16
  • 27
  • **foo** is the name of a device on local LAN network. I am trying to access that device through this URL. – Rishi Jasapara Apr 23 '14 at 18:35
  • What server technology are you using to serve web pages on foo? – Vlad Stirbu Apr 23 '14 at 18:49
  • If you have already hardcoded the foo.local in your application, the feature that you are looking for is multicast name resolution mDNS (e.g. mapping foo.local to an IP address). ZeroConf plugin provides DNS service discovery and is not a direct replacement for mDNS. You might want to look at the full API provided by JmDNS and use only the mDNS part if that exists. – Vlad Stirbu Apr 24 '14 at 09:06
  • Stribu: **foo** is actually a hardware device **arduino**, this app is basically being built to try and ping the arduino through the app via this fixed URL. – Rishi Jasapara Apr 24 '14 at 10:13
  • what about using this on your arduino to advertise the service: http://forum.pjrc.com/threads/24481-ZeroConf-Bonjour-Library – Vlad Stirbu Apr 25 '14 at 06:36