Android 間での RFCOMM チャネルの Bluetooth 通信 1/2

ここでは二つの Android 端末間で、Bluetooth を用いた通信を行う方法を示します。

Bluetooth に必要なパーミッションの設定発見の方法ペアリング済みのデバイスの取得 など、 他の記事で書いた内容については、先に目を通しておくとよいと思います。

尚、念のため記載するとここのコードは Nexus 5X (Android 7.1.1) と Nexus 7 2012 (Android 5.1.1) で動作確認しました。

Bluetooth 接続概要

Bluetooth での通信は TCP/IP のソケット通信と同様に考えることができます。

接続を受け付ける「サーバー」側と、接続しにいく「クライアント」側という二つの役割があります。

全体像を図にするとおよそ次のようになります。

サーバー側の処理

上図のサーバー側の処理を切り出して説明します。

サーバー側は、BluetoothAdapter の getDefaultAdapter() メソッドで BluetoothAdapter のインスタンスを取得します。 BluetoothAdapter の listenUsingRfcommWithServiceRecord メソッドを呼び出し、サーバーソケット (BluetoothServerSocket) を作成します。

このとき、サービス名とサービスを識別するための UUID を指定します。

これにより Android の SDP (サービス発見プロトコル) サーバーに、 サービス名と UUID を元に SDP レコードが作成されます。

続いて、サーバーソケットの accept() メソッドを呼ぶとサーバーは、クライアントからの接続要求待ち状態になります。

accept() メソッドはブロッキングメソッドです。つまり、接続要求があるまで返りません。このため、accept は UI スレッドとは異なる ワーカースレッドにて呼び出す必要があります。

クライアントからの接続要求があると、要求に含まれる UUID を元に SDP レコードを探します。

指定した UUID を持つサービスが存在すれば、RFCOMM 通信チャネルが作成され、 関連付けされた Bluetooth ソケットが作成されます。

ここで accept メソッドは BluetoothSocket を返して戻ります。この BluetoothSocket でクライアントの通信を行います。

getInputStream() 及び getOutputStream() メソッドによって、それぞれ入力ストリーム、出力ストリームが取得できます。このストリームに対する入出力がクライアントのデータ通信となります。

同じ通信チャネルを複数の端末と共有しないので、サーバーソケット (BluetoothServerSocket) はクローズします。

クライアント側の処理

次はクライアント側について説明します。

クライアント側もまずは BluetoothAdapter を取得する所から始めます。BluetoothAdapter の getDefaultAdapter メソッドを呼びます。

次に、接続するサーバーデバイスを探します。あらかじめペアリングを行っているデバイスは、BluetoothAdapter の getBondedDevices メソッドで直ちに取得できます。

BluetoothDevice オブジェクトを、ペアリングデバイスリスト (Bonded リスト) もしくは発見によって取得したら、接続するサービスの UUID を指定して createRfcommSocketToServiceRecord メソッドを呼び出します

UUID については独自のサービスであれば自前で作成した UUID を使えば OK です。 HC-06 等の Bluetooth UART アダプター等に接続する際には、 SPP (シリアルポートプロファイル) の UUID である 00001101-0000-1000-8000-00805F9B34FB を使います

尚、認証及び暗号化通信を行わない通信チャネルを作成するときは createInsecureRfcommSocketToServiceRecord メソッドを使います。HC-05, HC-06 等はセキュアチャネルをサポートします。

さて、BluetoothSocket を取得したら、connect() メソッドで接続要求を行います。

サーバー側が起動しており、かつ指定した UUID にあたるサービスが提供されている場合、connect は成功します。connect は処理が完了するまで返らないブロッキングコールです。 失敗した場合は IOException が投げられます。

全て正常に完了したら、BluetoothSocket から取得できる I/O ストリームを用いて、サーバー側とデータ通信が可能になります。

上記を踏まえ、Android 端末間で Bluetooth 通信を行うコードを書いてみましょう。

» Android 間での RFCOMM チャネルの Bluetooth 通信 2/2

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Android 開発入門