web-dev-qa-db-ja.com

Bonjourの実装Android

Androidアプリにbonjour/zero confを実装しようとしています。利用可能なすべてのデバイスを検索するために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台のPCとMacがあります。

私もこのコードからリストを取得しようとしました:

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

listenerは、アクティビティのonCreateで定義されています。しかし、これもデバイスを返しませんでした。

助けて、私がここで間違っていることを提案してください。どんな助けでもありがたいです!

30
mudit

Android 4.1は Network Service Discovery を追加します。これは、異なる用語でBonjourスタックをラップしているようです。また、DNS-SD(およびUPnP?)を直接公開する Android.net.wifi.p2p.WifiP2pManager と呼ばれる下位レベルのAPIも表示されます。

根底にあるmDNSResponderデーモンは常に実行されているようには見えず、私が知る限り、システム全体のDNSルックアップ(たとえばブラウザから)には使用されないことに注意してください。

17
natevw

コードについて具体的なヘルプは提供できませんが、AndroidおよびmDNSには、少なくとも一部のハンドセットと(私は)エミュレーターで)問題があると確信しています。

詳細はこちら:

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

5
CMF

上記のコメントで述べたように、ネイティブの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 library をlibsフォルダーとbuild.gradleに追加する必要があることにも注意してください。バージョン2.1.7を使用しました。

4
Matt__C

あなたの電話でマルチキャストが有効になっているという事実を知っていますか? http://home.heeere.com/tech-androidjmdns.html を参照してください。

そして、おそらく「_http.tcp」サービスの代わりに「_ipp._tcp.local」(または同様の何か)を探す必要があります。しかし、それはテストのためだけですよね? :-)

4
gmw

「bonjourブラウザ」など、AndroidのPlayストアにある既存のツールを使用してローカルネットワークを最初にスキャンし、スキャンするサービスがあることを確認できます。次に、jmDNSキーワードをチェックしてネットワークをスキャンできます。

しかし、jmDnsが一部のAndroid 4.xデバイスで動作しない)という既知の問題があります。

3
Zephyr