我正在制作第一个Android版PhoneGap应用程序,它需要mDNS解析。由于无法在Android(v4.1之前的版本)上解析“ .local”地址,因此我已将ZeroConf库与JmDNS.jar文件一起使用。我已经从this GitHub repository获得了插件的参考,您可能想看看。
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>
现在我的问题:
我想调用一个固定的URL,例如index.html页面中的http://foo.local/abc/,它应该解析为本地IP地址。我该如何实现?我知道必须使用JavaScript来完成,但是如何解决呢?我搜索了许多很多文章,直到这里。如果您能进一步指导我,我将不胜感激。
最佳答案
在收到“设备就绪”事件后的某个地方,您可以注册以观看在Bonjour上发布的服务:ZeroConf.watch("_http._tcp.local.", function (service) { // do something with the service}
但是,仅使用ZeroConf插件是不够的,因为您还需要在foo.local提供内容的服务器通过bonjour通告其HTTP服务。如果使用node.js服务器,则可以使用此module。