2011-01-11 46 views
26

Tôi đang cố triển khai bonjour/zero conf trên ứng dụng Android của mình. Tôi đang sử dụng thư viện jmDns để tìm kiếm tất cả các thiết bị có sẵn. Đây là mã mà tôi đang sử dụng để tìm kiếm các thiết bị trong cùng một mạng:Triển khai Bonjour trên Android

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(); 
     } 
    } 
} 

Về cơ bản, tôi thêm chúng vào danh sách để tôi có thể hiển thị danh sách tất cả các thiết bị có sẵn. Bây giờ khi tôi đang chạy mã này, tôi không nhận được ngoại lệ/không có gì giống như lỗi. Nhưng mặt khác, không có gì được thêm vào danh sách của tôi [PS: có ít nhất 5-6 PC và Mac đang có trong mạng.

Tôi cũng đã cố gắng để có được danh sách các từ mã này:

jmdns.addServiceListener("_http._tcp.local.", listener); 

listener được định nghĩa trong onCreate của hoạt động này. Nhưng điều này cũng không trả lại bất kỳ thiết bị nào.

Vui lòng trợ giúp, đề xuất những gì tôi đang làm sai ở đây. Bất kỳ trợ giúp được đánh giá cao!

+0

Bạn không nên sử dụng mã này: if (! InetAddress.isLoopbackAddress() &&! InetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) – Radu

+0

@mudit.Tôi hiểu một số thời gian đã trôi qua kể từ khi bạn gặp phải vấn đề này. Bạn đã thử liệt kê theo "_http._tcp" thay vì "_http._tcp.local." Tôi không thể giải thích tại sao, nhưng nó làm cho sự khác biệt trong trường hợp của tôi. Cho đến nay nó chỉ tạo sự khác biệt khi sử dụng NsdManager (khám phá Android tiêu chuẩn). Tôi sẽ biết làm thế nào nó có thể ảnh hưởng đến JmDNS tra cứu sau này, ngay sau khi người dùng của chúng tôi với vấn đề sẽ thử nó ... – vladimir

Trả lời

4

Bạn có biết một thực tế rằng multicast được kích hoạt trên điện thoại của bạn? Xem http://home.heeere.com/tech-androidjmdns.html.

Và có lẽ bạn nên tìm kiếm "_ipp._tcp.local" (hoặc một cái gì đó tương tự) thay vì "_http.tcp" dịch vụ. Nhưng đó chỉ là để thử nghiệm, phải không? :-)

17

Android 4.1 thêm Network Service Discovery dường như chỉ gói gọn ngăn xếp Bonjour theo các cụm từ khác nhau. Tôi cũng thấy một API cấp thấp hơn được gọi là android.net.wifi.p2p.WifiP2pManager để hiển thị trực tiếp DNS-SD (cũng như UPnP?).

Lưu ý rằng trình nền mDNSResponder cơ bản dường như không chạy mọi lúc và không được sử dụng để tra cứu DNS toàn hệ thống (ví dụ: từ trình duyệt) theo như tôi có thể biết ngay bây giờ.

+0

Cả hai dịch vụ mạng Discovery và Bonjour là triển khai của [Zeroconf] (http://www.zeroconf.org/) , không gói cái kia. – Trisped

+5

Xin vui lòng không sử dụng này cho đến khi android giải quyết các vấn đề liên quan đến dịch vụ mạng Discovery. Các vấn đề này được đề cập là: 1) .http: //code.google.com/p/android/issues/detail? Id = 39583 2) .https: //code.google.com/p/android/issues/detail ? id = 35585 3) .http: //code.google.com/p/android/issues/detail? id = 39750 –

+0

Tôi thấy rằng Android NDS hoạt động tốt hơn mdnsjava được tham chiếu trong một số nhận xét khác tại đây (sử dụng Android 5). Nó vẫn không cho tôi những kết quả tương tự mà tôi thấy trong ứng dụng Bonjour Browser không may. – Bill

2

Bạn có thể sử dụng công cụ hiện có từ Cửa hàng Play của Android để quét mạng cục bộ trước, như "trình duyệt bonjour" để đảm bảo có các dịch vụ bạn muốn quét. Sau đó, bạn có thể kiểm tra từ khóa jmDNS để quét mạng.

Nhưng có một vấn đề đã biết là jmDns không hoạt động trên một số thiết bị Android 4.x.

+0

Xin chào @Zephyr. Bạn nói rằng nó được biết đến vấn đề mà jmDns không hoạt động trên một số thiết bị Android 4.x. Bạn có biết thêm chi tiết? Lý do là gì? Chúng tôi có một người dùng với vấn đề này. Bonjour Browser hoạt động tốt cho anh ta nhưng không có gì có thể được phát hiện qua thư viện jmDns. Cho đến nay bình luận của bạn ở đây - xác nhận duy nhất rằng không chỉ tôi gặp vấn đề này với jmDns ... – vladimir

+1

Xin chào @vladimir, trong quá trình phát triển, chúng tôi xác nhận rằng JmDNS không hoạt động trên một số thiết bị Android 4.1, nó hoạt động trên các thiết bị dưới 4.1 phiên bản. lý do có thể là trong việc thực hiện các JmDNS trên nền tảng Android, bởi vì việc thực hiện ban đầu của Bonjour là trên nền tảng iOS, chỉ cần không sử dụng được như iOS. Nhân tiện, NSD bản địa của Android không đáng tin cậy trên các phiên bản 4.x đầu tiên, nó bị treo rất nhiều. – Zephyr

+0

@ Zyphyr, vậy thư viện nào bạn đang sử dụng để khám phá cuối cùng? Tôi đang nghĩ đến việc khám phá thông qua cả JmDNS và NSD và sau đó hiển thị một số kết quả tổng hợp cho người dùng. Bạn có nghĩ rằng có những lựa chọn tốt hơn cho bây giờ? – vladimir

3

Như đã lưu ý trong các nhận xét ở trên, hỗ trợ Android gốc không hoạt động và/hoặc không được triển khai hoàn toàn để cho phép truy xuất bản ghi TXT (như của Android v5.1). Tôi cũng không thể nhận được thư viện jmDns để làm việc cho việc khám phá. Cuối cùng tôi đã tìm thấy mdnsjava project và nó hoạt động rất dễ dàng đối với tôi. Lưu ý rằng mã mẫu của nó không chính xác. Dưới đây là một số mẫu mã tôi sử dụng để tìm đồng bộ tất cả các máy in 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(); 
    } 

Cũng lưu ý rằng bạn cần phải thêm dnsjava library để libs của bạn thư mục và build.gradle của bạn. Tôi đã sử dụng phiên bản 2.1.7.