Android Bluetooth開発例の解析
携帯電話を使う時、ブルートゥース通信は私達に多くの便利をもたらしてくれます。Android携帯ではどのようにBluetooth開発が行われますか?本論文は実例的にAndroid Bluetooth開発の知識を説明する。
1、ブルートゥースを使用する応答権限
XML/HTMLコード
ここではまずBluetooth Adapterの中心的な操作を理解する必要があります。
Bluetooth AdapterのstartDisccovery()を使ってBluetoothデバイスを検索します。
startDisccovery()メソッドは非同期の方法で、呼び出したらすぐに戻ります。この方法は他のBluetoothデバイスの検索を行い、このプロセスは12秒続く。この方法の呼び出し後、検索プロセスは実際にはSystem Serviceで行われるので、cancel Disccovery()メソッドを呼び出して、discovery要求を実行していないときに呼び出すことができる。
Discoveryを要求したら、システムはBluetoothデバイスの検索を開始します。この過程で、システムは以下の3つの放送を送信します。
ACTION_DISCOVERY_START:検索開始
ACTION_DISCOVERY_FINISHED:検索終了
ACTION_FOUND:設備を見つけました。このIntentには二つのextra fieldsが含まれています。EXTRA_DEVICEとEXTRA_CLASSには、BluetooDeviceとBluetooth Classが含まれています。
いくつかの機能を実現するために、対応するBroadcastReceiverを自身で登録して応答放送を受信することができます。
二つのBluetoothデバイス間の接続を提案するつもりであれば、サーバー側とクライアント側のメカニズムを実現しなければならない。二つのデバイスが同じRFC OMM chanelの下でそれぞれ一つの接続を持つBluetooth Socketは、この二つのデバイスが接続を確立したと言える。
サーバーデバイスとクライアントデバイスがBluetooth Socketを取得する方法は違います。サーバーデバイスはacceptedのincomping connectionによって取得され、クライアントデバイスはサーバに行くRFCOMMチャンネルを開くことによって取得される。
サーバー側の実装
Bluetooth AdapterのlistenUsingRfcomWithServiceRecord(String,UUUID)方法を呼び出して、Bluetooth ServerSocketを取得する。
Bluetooth ServerSocketのaccept()を呼び出して接続要求を監督し、要求を受信したらBluetooth Socketのインスタンスを返します。
acceptで他の接続をしたくない場合は、Bluetooth Server Socketのclose()メソッドを呼び出してリソースを解放する(この方法を呼び出した後、以前に得られたBluetooth Socketの例は、closeではありません。しかし、RFCOMMは一つの時間で一つのチャンネルにしか接続できないので、acceptに接続した後、Bluetooth ServerSocketをcloseに落とします。
検索でサーバー端のBluetooth Serviceが得られます。
Bluetooth Serviceを呼び出したlistenUsingRfcomWithServiceRecord(String,UUID)メソッドは、Bluetooth Socketを取得する。
Bluetooth Socketのconnect(この方法はblock方法)を呼び出して、UIDがサーバ端のUUIDとマッチングしてサーバ端のacceptに接続されると、connect()方法は戻ります。
注意:connect()メソッドを呼び出す前に、現在は検索デバイスがないと判定しなければ、接続が非常に遅くなり、失敗しやすいです。
Bluetooth Socketのget InputStream()とget OutputStream()の方法でInputStreamとOutputStreamをそれぞれ取得します。
read(bytes[])とwrite(bytes[])の方法を使ってそれぞれ読み書きを行います。
注意:read(bytes[])方法は常にblockであり、流れから情報を読み取ることができますが、write(bytes[])方法はいつものblockではありません。
1、ブルートゥースを使用する応答権限
XML/HTMLコード
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
2、本機のブルートゥースモジュールを配置するここではまずBluetooth Adapterの中心的な操作を理解する必要があります。
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
//
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 0x1);
//
adapter.enable();
//
adapter.disable();
// ( 120 , 300 )
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);// ( 300 )
3、ブルートゥース設備の検索Bluetooth AdapterのstartDisccovery()を使ってBluetoothデバイスを検索します。
startDisccovery()メソッドは非同期の方法で、呼び出したらすぐに戻ります。この方法は他のBluetoothデバイスの検索を行い、このプロセスは12秒続く。この方法の呼び出し後、検索プロセスは実際にはSystem Serviceで行われるので、cancel Disccovery()メソッドを呼び出して、discovery要求を実行していないときに呼び出すことができる。
Discoveryを要求したら、システムはBluetoothデバイスの検索を開始します。この過程で、システムは以下の3つの放送を送信します。
ACTION_DISCOVERY_START:検索開始
ACTION_DISCOVERY_FINISHED:検索終了
ACTION_FOUND:設備を見つけました。このIntentには二つのextra fieldsが含まれています。EXTRA_DEVICEとEXTRA_CLASSには、BluetooDeviceとBluetooth Classが含まれています。
いくつかの機能を実現するために、対応するBroadcastReceiverを自身で登録して応答放送を受信することができます。
// ACTION_FOUND BroadcastReceiver
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// array adapter, ListView
mArrayAdapter.add(device.getName() + "
" + device.getAddress());
}
}
};
// BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); //
4、ブルートゥースソケット通信二つのBluetoothデバイス間の接続を提案するつもりであれば、サーバー側とクライアント側のメカニズムを実現しなければならない。二つのデバイスが同じRFC OMM chanelの下でそれぞれ一つの接続を持つBluetooth Socketは、この二つのデバイスが接続を確立したと言える。
サーバーデバイスとクライアントデバイスがBluetooth Socketを取得する方法は違います。サーバーデバイスはacceptedのincomping connectionによって取得され、クライアントデバイスはサーバに行くRFCOMMチャンネルを開くことによって取得される。
サーバー側の実装
Bluetooth AdapterのlistenUsingRfcomWithServiceRecord(String,UUUID)方法を呼び出して、Bluetooth ServerSocketを取得する。
Bluetooth ServerSocketのaccept()を呼び出して接続要求を監督し、要求を受信したらBluetooth Socketのインスタンスを返します。
acceptで他の接続をしたくない場合は、Bluetooth Server Socketのclose()メソッドを呼び出してリソースを解放する(この方法を呼び出した後、以前に得られたBluetooth Socketの例は、closeではありません。しかし、RFCOMMは一つの時間で一つのチャンネルにしか接続できないので、acceptに接続した後、Bluetooth ServerSocketをcloseに落とします。
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(socket);
mmServerSocket.close();
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
クライアントの実装検索でサーバー端のBluetooth Serviceが得られます。
Bluetooth Serviceを呼び出したlistenUsingRfcomWithServiceRecord(String,UUID)メソッドは、Bluetooth Socketを取得する。
Bluetooth Socketのconnect(この方法はblock方法)を呼び出して、UIDがサーバ端のUUIDとマッチングしてサーバ端のacceptに接続されると、connect()方法は戻ります。
注意:connect()メソッドを呼び出す前に、現在は検索デバイスがないと判定しなければ、接続が非常に遅くなり、失敗しやすいです。
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
5、接続管理(データ通信)Bluetooth Socketのget InputStream()とget OutputStream()の方法でInputStreamとOutputStreamをそれぞれ取得します。
read(bytes[])とwrite(bytes[])の方法を使ってそれぞれ読み書きを行います。
注意:read(bytes[])方法は常にblockであり、流れから情報を読み取ることができますが、write(bytes[])方法はいつものblockではありません。
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main Activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
以上はAndroid Bluetoothの開発の簡単な例コードについて、引き続き関連資料を整理します。ありがとうございます。