2011-01-11 58 views
26

我想在我的android应用上实现bonjour/zero conf。我正在使用jmDns库来搜索所有可用的设备。下面是我使用的同一网络中搜索设备代码:Android上的Bonjour实现

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

你不应该使用这段代码:if(!inetAddress.isLoopbackAddress()&&!inetAddress.isLinkLocalAddress()&& inetAddress.isSiteLocalAddress()) – Radu 2013-03-13 09:20:57

+0

@mudit。我知道自从遇到这个问题以来已经有一段时间了。你是否尝试用“_http._tcp”而不是“_http._tcp.local。”列出。我无法解释为什么,但在我的情况下却有所不同。到目前为止,只有在使用NsdManager(标准Android发现)时才会有所不同。只要我们的用户遇到问题,我会立即知道它是如何影响JmDNS查找的...... – vladimir 2014-10-30 18:41:52

回答

4

你知道一个事实,即组播您的手机上启用了?见http://home.heeere.com/tech-androidjmdns.html

而你应该寻找“_ipp._tcp.local”(或类似的东西)而不是“_http.tcp”服务。但这只是为了测试,对吧? :-)

17

Android 4.1增加了Network Service Discovery这似乎只是用不同的术语来包装Bonjour栈。我还看到一个名为android.net.wifi.p2p.WifiP2pManager的低级API,它直接暴露DNS-SD(以及UPnP?)。

请注意,底层的mDNSResponder守护进程似乎并不是一直在运行,并且不能用于系统范围的DNS查找(例如从浏览器),只要我现在可以告诉。

+0

Network Service Discovery和Bonjour都是[Zeroconf](http://www.zeroconf.org/)的实现, ,而不是包装其他。 – Trisped 2013-05-08 23:58:52

2

您可以使用Android Play Store中的现有工具先扫描本地网络,例如“bonjour browser”,以确保您想要扫描的服务。然后你可以检查jmDNS关键字来扫描网络。

但是有一个已知问题,jmDns在某些Android 4.x设备上不起作用。

3

正如在上面的评论中指出的那样,本机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版本。