Bluetooth通信の実装|Android開発
AndroidアプリでBluetooth通信を実装する方法です。
Bluetooth接続では、受信側と送信側で同一のUUIDを使用します。下記はシリアルポートプロファイル(SPP)でデータを送信するBluetooth機器との通信サンプルです。
前提条件
- 接続デバイスとはペアリング済みにしておきます
AndroidManifest.xml
に以下の権限を追加しておきます
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
Bluetooth 通信手順
BluetoothAdapter
を取得します
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
BluetoothAdapter mBluetoothAdapter;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// エラー: Bluetooth なし.
}
- ペアリング済みのデバイス一覧を取得します
getBondedDevices()
はエラー時にnull
を返すためエラー判定が必要です - 取得したデバイス一覧から接続デバイスを検索します
String deviceName = "接続デバイス名";
// 対象 Bluetooth デバイスのシリアルポートプロファイルに接続する.
SerialPortProfileConnectThread connectTread = null;
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// getBondedDevices() はエラー時に null を返すのでチェックが必要.
if (pairedDevices != null) {
for (BluetoothDevice device : pairedDevices) {
if (deviceName.equals(device.getName())) {
connectTread = new SerialPortProfileConnectThread(device);
break;
}
}
}
if (connectTread == null) {
// エラー: 接続デバイスなし.
}
SerialPortProfileConnectThread
クラスはシリアルポートプロファイルを使ってBluetooth接続するクラスです。
実際の接続処理は親のBluetoothConnectThread
クラスで実装しています。
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import java.util.UUID;
public class BluetoothConnectThread extends Thread {
protected String TAG = "BluetoothConnectThread";
protected final BluetoothSocket mmSocket;
public BluetoothSocket getSocket() {
return mmSocket;
}
public BluetoothConnectThread(BluetoothDevice device, UUID uuid) {
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
e.printStackTrace();
// NOP.
}
mmSocket = tmp;
}
public void run() {
if (mmSocket == null) {
return;
}
try {
mmSocket.connect();
} catch (IOException e) {
e.printStackTrace();
try {
mmSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return;
}
Log.i(TAG, "Bluetooth connecting.");
}
}
import android.bluetooth.BluetoothDevice;
import java.util.UUID;
public class SerialPortProfileConnectThread extends BluetoothConnectThread {
// "00001101-0000-1000-8000-00805f9b34fb" = SPP (シリアルポートプロファイル) の UUID.
public static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
public SerialPortProfileConnectThread(BluetoothDevice device) {
super(device, SPP_UUID);
TAG = "SerialPortProfileConnectThread";
}
}
- 接続前に Bluetooth デバイスの検索を停止します
mBluetoothAdapter.cancelDiscovery();
SerialPortProfileConnectThread
を開始し、ソケットを接続します
connectTread.start();
// 接続完了を待つ.
// 下記は sleep() を使用した暫定処理です.
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
接続が完了したら、このスレッドは終了します。
Bluetooth 接続完了前に次項の
Bluetooth 接続完了前に次項の
BluetoothReceiveTask
でデータ読み出しを行うと例外が発生します。
- データ受信用のスレッドを生成・実行します
この時、接続完了したソケットを使用します
private BluetoothReceiveTask mReceiveTask;
mReceiveTask = new BluetoothReceiveTask(connectTread.getSocket());
mReceiveTask.start();
BluetoothReceiveTask
では接続機器の仕様に合わせて受信したデータを処理します。
import android.bluetooth.BluetoothSocket;
import java.io.IOException;
import java.io.InputStream;
class BluetoothReceiveTask extends Thread {
public static final String TAG = "BluetoothReceiveTask";
protected InputStream mInputStream;
protected BluetoothSocket mSocket;
protected volatile boolean mIsCancel;
public BluetoothReceiveTask(BluetoothSocket socket) {
mIsCancel = false;
mSocket = null;
mInputStream = null;
if (socket == null) {
Log.e(TAG, "parameter socket is null.");
return;
}
try {
mInputStream = socket.getInputStream();
mSocket = socket;
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
byte[] buffer = new byte[64];
int readSize;
Log.i(TAG, "start read task.");
while (mInputStream != null) {
if (mIsCancel) {
break;
}
try {
readSize = mInputStream.read(buffer);
if (readSize == 64) {
// 処理.
} else {
Log.e(TAG, "NG " + readSize + "byte");
}
Thread.sleep(0);
} catch (IOException e) {
e.printStackTrace();
break;
} catch (InterruptedException e) {
Log.e(TAG, "InterruptedException!!");
// NOP.
break;
}
}
Log.i(TAG, "exit read task.");
}
public void cancel() {
mIsCancel = true;
}
public void finish() {
if (mSocket == null) {
return;
}
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上で Bluetooth 機器とシリアルポートプロファイルを使ったデータ通信が可能です。
Bluetooth通信終了処理
Bluetooth通信終了時はデータ受信のスレッドを終了させます。
if (mReceiveTask != null) {
mReceiveTask.cancel();
}
// キャンセル完了を待つ処理など.
if (mReceiveTask != null) {
mReceiveTask.finish();
mReceiveTask = null;
}
