我正在尝试在我的Android应用上实现bonjour / zero conf。我正在使用jmDns库来搜索所有可用的设备。以下是我用于搜索同一网络中设备的代码:
public class ListDevices extends ListActivity {
JmDNS jmdns;
JmDNSImpl impl;
MulticastLock lock;
protected ServiceListener listener;
protected ServiceInfo info;
public ListView lv;
public ArrayList<String> deviceList;
public int cancel = 0;
public final static String TAG = "ListDevices";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
deviceList = new ArrayList<String>();
showAllPrinters();
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, deviceList));
lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(),
((TextView) view).getText(), Toast.LENGTH_SHORT).show();
}
});
this.listener = new ServiceListener() {
public void serviceAdded(ServiceEvent event) {
deviceList.add("Service added : " + event.getName() + "."
+ event.getType());
Log.v(TAG, "Service added : " + event.getName() + "."
+ event.getType());
}
public void serviceRemoved(ServiceEvent event) {
deviceList.add("Service removed : " + event.getName() + "."
+ event.getType());
Log.v(TAG, "Service removed : " + event.getName() + "."
+ event.getType());
}
public void serviceResolved(ServiceEvent event) {
deviceList.add("Service resolved: " + event.getInfo());
Log.v(TAG, "Service resolved: " + event.getInfo());
}
};
}
public void showAllPrinters() {
Log.d("ListDevices", "in showAllPrinters");
try {
WifiManager wifi = (WifiManager)
getSystemService(Context.WIFI_SERVICE);
lock = wifi.createMulticastLock("fliing_lock");
lock.setReferenceCounted(true);
lock.acquire();
InetAddress inetAddress = getLocalIpAddress();
jmdns = JmDNS.create(inetAddress, "TEST");
ServiceInfo[] infos = jmdns.list("_http._tcp.local.");
if (infos != null && infos.length > 0) {
for (int i = 0; i < infos.length; i++) {
deviceList.add(infos[i].getName());
}
} else {
deviceList.add("No device found.");
}
impl = (JmDNSImpl) jmdns;
} catch (IOException e) {
e.printStackTrace();
}
}
public InetAddress getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface
.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = (NetworkInterface) en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf
.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = (InetAddress) enumIpAddr
.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress;
}
}
}
} catch (SocketException ex) {
Log.e("ListDevices", ex.toString());
}
return null;
}
@Override
protected void onPause() {
super.onPause();
if (isFinishing()) {
lock.release();
}
}
}
基本上,我将它们添加到列表中,以便显示所有可用设备的列表。现在,当我运行此代码时,我没有异常/没有错误。但另一方面,我的列表中没有添加任何内容[PS:网络中至少有5-6台PC和Mac。
我也尝试从这段代码中获取列表:
jmdns.addServiceListener("_http._tcp.local.", listener);
listener
在活动的onCreate
中定义。但这也没有返回任何设备。
请帮助,建议我在这里做错了什么。任何帮助表示赞赏!
答案 0 :(得分:17)
Android 4.1添加了Network Service Discovery,它似乎只是以不同的方式包装了Bonjour堆栈。我还看到一个名为android.net.wifi.p2p.WifiP2pManager的低级API直接暴露DNS-SD(以及UPnP?)。
请注意,底层的mDNSResponder守护程序似乎并不是一直在运行,并且就目前我所知,它不用于系统范围的DNS查找(例如,从浏览器)。
答案 1 :(得分:5)
我无法向您提供有关代码的任何具体帮助,但我非常确定Android和mDNS存在问题,至少对于某些手机和(我相信)模拟器而言。
此处提供更多信息:
http://rgladwell.wordpress.com/2010/04/18/gotchas-android-and-multicast-dns/
答案 2 :(得分:4)
您知道手机上启用了多播的事实吗?请参阅http://home.heeere.com/tech-androidjmdns.html。
你应该寻找“_ipp._tcp.local”(或类似的东西)而不是“_http.tcp”服务。但这只是为了测试,对吧? : - )
答案 3 :(得分:4)
如上面的评论中所述,本机Android支持无法正常工作和/或未完全实现以允许检索TXT记录(从Android v5.1开始)。我也无法让jmDns库用于发现。我终于找到了mdnsjava project,对我来说很容易。请注意,其示例代码不正确。以下是我用来同步查找所有IPP打印机的一些代码示例:
String type[] = {"_ipp._tcp.local."};
Lookup resolve = null;
try {
resolve = new Lookup(type, Type.ANY, DClass.IN);
ServiceInstance[] records = resolve.lookupServices();
for (ServiceInstance record : records) {
Log.d(TAG, record.toString());
Map txtMap = record.getTextAttributes();
}
} catch (IOException e) {
e.printStackTrace();
}
另请注意,您需要将dnsjava library添加到libs文件夹和build.gradle中。我使用的是2.1.7版本。
答案 4 :(得分:3)
您可以使用Android Play商店中的现有工具首先扫描本地网络,例如“bonjour浏览器”,以确保您有要扫描的服务。然后,您可以检查jmDNS关键字以扫描网络。
但是有一个已知的问题是jmDns在某些Android 4.x设备上不起作用。