NsdServiceは時期尚早?
androidからのBonjourをテストするのに最初JmDNSの実装を使う予定だったのだが、android 4.1以降サポートされたandroid.net.nsdバッケージがmDNS(Multicast DNS)とDNS-SD(DNS based Service Discovery)をサポートしたとのことなので、まずはそちらから試してみることにした。
NsdManagerによりサービスを探索する疑似コード
NsdManager nsdManager = (NsdManager) getSystemService(NSD_SERVICE); nsdManager.discoverServices("_ipp._tcp.local.", NsdManager.PROTOCOL_DNS_SD, new NsdManager.DiscoveryListener() { @Override public void onStopDiscoveryFailed(String serviceType, int errorCode) { } @Override public void onStartDiscoveryFailed(String serviceType, int errorCode) { } @Override public void onServiceLost(NsdServiceInfo serviceInfo) { } @Override public void onServiceFound(NsdServiceInfo serviceInfo) { } @Override public void onDiscoveryStopped(String serviceType) { } @Override public void onDiscoveryStarted(String serviceType) { } });
サービスを探索するコードはNsdManager.DiscoveryListenerをnsdManagerに登録することにより、各種イベントが発生した際にリスナのメソッドが呼ばれる仕組みであり、非常に明快だ。
しかしまずはEmulator(4.2と4.2)で実行して見ると、テストコードが全く動かない。それどころかEmulatorがリブートしているようだ。(GALAXY Nexus実機(android 4.2.2)でもテストしたが、本当にリブートする)
ログを拾ってみると、NsdManager#discoverServicesの実行後にFATAL EXCEPTIONを発生していることが分かった。
03-03 17:11:44.229: D/NsdService(9010): Discover services 03-03 17:11:44.229: W/dalvikvm(9010): threadid=44: thread exiting with uncaught exception (group=0xa6fb7288) 03-03 17:11:44.229: E/AndroidRuntime(9010): *** FATAL EXCEPTION IN SYSTEM PROCESS: NsdService 03-03 17:11:44.229: E/AndroidRuntime(9010): java.lang.NullPointerException 03-03 17:11:44.229: E/AndroidRuntime(9010): at com.android.server.NsdService$ClientInfo.access$1200(NsdService.java:800) 03-03 17:11:44.229: E/AndroidRuntime(9010): at com.android.server.NsdService$NsdStateMachine$EnabledState.requestLimitReached(NsdService.java:243) 03-03 17:11:44.229: E/AndroidRuntime(9010): at com.android.server.NsdService$NsdStateMachine$EnabledState.processMessage(NsdService.java:291) 03-03 17:11:44.229: E/AndroidRuntime(9010): at com.android.internal.util.StateMachine$SmHandler.processMsg(StateMachine.java:895) 03-03 17:11:44.229: E/AndroidRuntime(9010): at com.android.internal.util.StateMachine$SmHandler.handleMessage(StateMachine.java:756) 03-03 17:11:44.229: E/AndroidRuntime(9010): at android.os.Handler.dispatchMessage(Handler.java:99) 03-03 17:11:44.229: E/AndroidRuntime(9010): at android.os.Looper.loop(Looper.java:137) 03-03 17:11:44.229: E/AndroidRuntime(9010): at android.os.HandlerThread.run(HandlerThread.java:60)
NsdManagerの取得は問題なく実行されているので内部の処理中に発生する例外だと思われるが、100%例外が発生する訳ではなくたまに問題無く動作したり、デバッグモードでは動いたりするのでバグの可能性が高い。