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%例外が発生する訳ではなくたまに問題無く動作したり、デバッグモードでは動いたりするのでバグの可能性が高い。

#当然既知だ。
Issue 39750 - android - NSD causes Nexus 7 device to spontaneously restart. - Android - An Open Handset Alliance Project - Google Project Hosting

Issue 35803 - android - NsdService causes fatal exception on discoverServices - Android - An Open Handset Alliance Project - Google Project Hosting