JSR-82を使ってBluetoothデバイスを探索する

JavaBluetoothデバイスを探索する方法のメモ

JavaとWiiリモコンをBluetoothでつなげてみようという記事に触発されて試してみました。といってもWiiリモコンをもっていないので、同じページで紹介されていたbluecoveを使ってみただけです。

bluecoveはDLLを含めて一つのJARファイルになっているので、ダウンロードしたファイルをクラスパスに通すだけで使うことができます。bluecove(JSR-82)を使って周囲のBluetoothデバイスを探索するプログラムはこんな感じです。

public void findRemoteDevices() {
	LocalDevice localDevice = LocalDevice.getLocalDevice();

	final Object lock = new Object();
	final DiscoveryAgent agent = localDevice.getDiscoveryAgent();
	boolean started = agent.startInquiry(DiscoveryAgent.GIAC, new DiscoveryListener() {
	
		@Override
		public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass clazz) {
			// デバイスが見つかった場合に呼び出される。
			// ここではデバイスのMACアドレスを表示している。
			System.out.println(remoteDevice.getBluetoothAddress());
		}

		@Override
		public void inquiryCompleted(int code) {
			// inquiryが終わると呼び出される。
			// codeはDiscoveryListenerクラスに定義がある。

			// 終了待ちを解除する。
			synchronized (lock) {
				lock.notifyAll();
			}
		}

		@Override
		public void serviceSearchCompleted(int arg0, int arg1) {
			// TODO Auto-generated method stub
		}
	
		@Override
		public void servicesDiscovered(int arg0, ServiceRecord[] arg1) {
			// TODO Auto-generated method stub
		}
	});

	// inquiryのスタートに失敗した場合はfalseになる。
	if (!started) {
		System.out.println(i + " inquiry started: " + result);
	}

	// inquiryが終わるまで待つ
	try {
		synchronized (lock) {
			lock.wait();
		}
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
}

最初にLocalDevice.getLocalDevice()で自身のBluetoothアダプタを取得し、それを使ってデバイス探索に利用するDiscoveryAgentを取得します。

DiscoveryAgentのstartInquiry()を呼び出すとデバイスの探索が始ります。探索の結果は2つ目の引数で指定したDiscoveryListenerインターフェイスに渡されます。また一つ目の引数には、GIACまたはLIACという引数が指定できるようですが、説明を見てもいま一つ違いが分かりませんでした。ひとまずGIACで動いたので深くは追及していません。

DiscoveryListenerのdeviceDiscovered()はデバイスが見つかると呼び出されます。引数のRemoteDeviceを利用することで、そのデバイスが提供するサービス等へのアクセスが可能となるようです。ここでは例として単にMACアドレスを表示するだけにしています。

IquiryComplete()はデバイスの探索が完了した際に呼び出されます。デバイスの探索には数十秒程度かかりますので、呼び出し側はlockオブジェクトを使って終了待ちを行っています。

それ以外のメソッドはデバイスの探索には特に必要ないようです。

周囲のデバイスを探すところまでは簡単にできるのですが、ここから先は各デバイスごとに色々と処理を行うみたいなので大変そうです。デバイスを探すだけだと意味がない気もしますが、Bluetoothデバイスで画面ロックくらいになら使えるかもしれません。