Подтвердить что ты не робот

Реализация Bonjour на Android

Я пытаюсь реализовать 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 активности. Но это также не вернуло никаких устройств.

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

Как отмечено в комментариях выше, встроенная поддержка 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.