Bonjour 在 Android 上的实现
我正在尝试在我的 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
中定义。但这也没有返回任何设备。
请帮忙,建议我在这里做错了什么。任何帮助表示赞赏!
I am trying to implement bonjour/zero conf on my android app. I am using jmDns library for searching the all the available devices. Here is the code that I am using for searching the devices in the same network:
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();
}
}
}
Basically, I am adding them in a list so that I can display a list of all available devices. Now when I am running this code, I am getting no exception/nothing like error. But on the other hand, nothing is added to my list [PS: there atleast 5-6 PCs and Macs are there in the network.
I also tried to get the list from this code:
jmdns.addServiceListener("_http._tcp.local.", listener);
listener
is defined in the onCreate
of the activity. But this also did not returned any device.
Please help, suggest what I am doing wrong here. Any help is appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Android 4.1 添加了似乎刚刚结束的网络服务发现 Bonjour 堆栈的不同说法。我还看到一个名为 android.net.wifi 的较低级别 API。 p2p.WifiP2pManager 直接公开 DNS-SD(以及 UPnP?)。
请注意,据我目前所知,底层 mDNSResponder 守护进程似乎并不一直在运行,并且不用于系统范围的 DNS 查找(例如,从浏览器)。
Android 4.1 adds Network Service Discovery that seems to be just wrapping up the Bonjour stack in different terms. I also see a lower-level API called android.net.wifi.p2p.WifiP2pManager that exposes DNS-SD (as well as UPnP?) directly.
Note that the underlying mDNSResponder daemon does not seem to be running all the time, and is not used for systemwide DNS lookups (e.g. from a browser) as far as I can tell right now.
我无法为您提供有关代码的任何具体帮助,但我非常确定 Android 和 mDNS 至少在某些手机和(我相信)模拟器上存在问题。
更多信息请参见:
http://rgladwell.wordpress。 com/2010/04/18/gotchas-android-and-multicast-dns/
I can't give you any specific help with the code but I'm pretty sure that there are issues with Android and mDNS at least with some handsets and (I believe) the emulator.
More information here:
http://rgladwell.wordpress.com/2010/04/18/gotchas-android-and-multicast-dns/
您知道您的手机上启用了多播吗?请参阅http://home.heeere.com/tech-androidjmdns.html。
您可能应该寻找“_ipp._tcp.local”(或类似的东西)而不是“_http.tcp”服务。但这只是为了测试,对吧? :-)
Do you know for a fact that multicast is enabled on your phone? See http://home.heeere.com/tech-androidjmdns.html.
And you should probably looking for "_ipp._tcp.local" (or something similar) instead of "_http.tcp" services. But that's just for testing, right? :-)
如上面的评论所述,原生 Android 支持无法正常工作和/或未完全实现以允许检索 TXT 记录(从 Android v5.1 开始)。我也无法让 jmDns 库用于发现。我终于找到了 mdnsjava 项目,它对我来说非常容易。请注意,其示例代码不正确。以下是我用来同步查找所有 IPP 打印机的一些代码示例:
另请注意,您需要添加 dnsjava 库< /a> 到您的 libs 文件夹和 build.gradle。我用的是2.1.7版本。
As noted in comments above, the native Android support is not working and/or not implemented completely to allow retrieval of TXT records (as of Android v5.1). I also could not get the jmDns library to work for discovery. I finally found the mdnsjava project and it worked very easily for me. Note that its sample code is not correct. Here is some sample of code I used to synchronously find all IPP printers:
Also note that you need to add the dnsjava library to your libs folder and your build.gradle. I used version 2.1.7.
您可以使用 Android Play 商店中的现有工具先扫描本地网络,例如“bonjour browser”,以确保有您要扫描的服务。然后你可以检查jmDNS关键字来扫描网络。
但有一个已知问题,即 jmDns 无法在某些 Android 4.x 设备上运行。
You may use an existing tool from Android's Play Store to scan the local network first, like "bonjour browser" to make sure there are the services you want to scan. Then you can check the jmDNS keyword to scan the network.
But there is a known issue that jmDns does not work on some Android 4.x devices.