Bonjour implementation on Android
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 inetAddr开发者_JAVA技巧ess = (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!
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.
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/
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? :-)
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:
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();
}
Also note that you need to add the dnsjava library to your libs folder and your build.gradle. I used version 2.1.7.
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.
精彩评论