2011-01-11 54 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版本。