Добрый день реализация на 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 деятельности. Но это также не вернуло ни одно устройство.

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

5 ответов

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

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

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

Больше информации здесь:

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

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

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

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

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

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

Другие вопросы по тегам