Добрый день реализация на Android - PullRequest
27 голосов
/ 11 января 2011

Я пытаюсь реализовать bonjour / zero conf в моем приложении для Android.Я использую библиотеку 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 ПК и Mac.

Я также пытался получить список из этого кода:

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

listener определяется в onCreate действия.Но это также не вернуло ни одно устройство.

Пожалуйста, помогите, подскажите, что я здесь не так делаю.Любая помощь приветствуется!

Ответы [ 5 ]

17 голосов
/ 31 октября 2012

Android 4.1 добавляет Обнаружение сетевых служб , которое, кажется, просто оборачивает стек Bonjour в разных терминах. Я также вижу низкоуровневый API с именем android.net.wifi.p2p.WifiP2pManager , который напрямую предоставляет DNS-SD (а также UPnP?).

Обратите внимание, что базовый демон mDNSResponder, кажется, не работает все время, и, насколько я могу судить, не используется для поиска DNS в масштабе всей системы (например, из браузера).

5 голосов
/ 11 января 2011

Я не могу дать вам никакой конкретной помощи с кодом, но я уверен, что есть проблемы с Android и mDNS, по крайней мере, с некоторыми телефонами и (я полагаю) эмулятором.

Дополнительная информацияздесь:

http://rgladwell.wordpress.com/2010/04/18/gotchas-android-and-multicast-dns/

4 голосов
/ 06 августа 2015

Как отмечено в комментариях выше, встроенная поддержка Android не работает и / или не реализована полностью, что позволяет извлекать записи TXT (начиная с Android v5.1). Я также не мог заставить библиотеку jmDns работать для обнаружения. Я наконец-то нашел проект mdnsjava , и он очень легко сработал для меня. Обратите внимание, что его пример кода не является правильным. Вот пример кода, который я использовал для синхронного поиска всех принтеров 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 в папку libs и свой build.gradle. Я использовал версию 2.1.7.

4 голосов
/ 11 августа 2011

Знаете ли вы, что многоадресная рассылка включена на вашем телефоне? Смотри http://home.heeere.com/tech-androidjmdns.html.

И вам, вероятно, следует искать «_ipp._tcp.local» (или что-то подобное) вместо служб «_http.tcp». Но это только для тестирования, верно? : -)

3 голосов
/ 11 июня 2014

Вы можете использовать существующий инструмент из магазина Android Play для сканирования локальной сети, например, «bonjour browser», чтобы убедиться, что есть сервисы, которые вы хотите сканировать. Затем вы можете проверить ключевое слово jmDNS для сканирования сети.

Но есть известная проблема, что jmDns не работает на некоторых устройствах Android 4.x.

...