Based on the android sample of BluetoothChat, I summarize a simple framework and essential APIs to detect/connect/open/close/ Bluetooth, setup as a server/client, send/receive message.
summary:
2 class, BluetoothChat.java, the main activity; BluetoothChatService.java, 3 threads. The bluetoothChat.java find the local bluetooth adapter, turn it on. It will instantiate a BluetoothChatService and start the AccetpThread as a server side. This thread calls a blocking fuction who will return a successful bluetooth socket and start the ConnectedThread for treating the incoming and outgoing message. If searching remote bluetooth is launched and one of them has been chosen to connect, the local bluetooth is client side, the ConnectThread starts and call a blocking function for a successful connection. Then the ConnectedThread will be launch,too, like the server side.1. Get local bluetooth adapter -- onCreate()
private BluetoothAdapter mBluetoothAdapter = null;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//The BluetoothAdapter lets you perform fundamental Bluetooth tasks. Represents the local device //Bluetooth adapter.
2. Turn on Bluetooth -- onStart()
if(!mBluetoothAdapter.isEnabled()){
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
// isEnabled: returns true if Bluetooth is currently enabled and ready for use
//ACTION_REQUEST_ENABLE: a system activity that allows the user to turn on Bluetooth
// An activity to ask the user whether turn on the bluetooth or not will be launched, and when it exited,
//call onActivityResult()
3. onResume() -- onPause()
4. onActivityResult() // called when the activity to start bluetooth is finished
switch (requestCode) {
case REQUEST_ENABLE_BT:
setupChat();
}
5. setupChat() // instancier BluetoothChatService() and resume the main activity
mChatService = new BluetoothChatService(this, mHandler);
6. onResume() // start the chat service as a server
if (mChatService != null) {
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
mChatService.start();
}
}
7. BluetoothChatService.start() -- AcceptThread.start() --
-- BluetoothChatService.connected() -- ConnectedThread.start()
//the thread AcceptThread wait for a connection, accept it, create a new server socket and
//start the thread ConnectedThread to handle all incoming and outgoing transmissions
public synchronized void start()
// synchronized function: block other synchronized functions before it finishes
case R.id.secure_connect_scan:
serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
return true;
}
if (mAcceptThread == null) {
mAcceptThread = new AcceptThread();
mAcceptThread.start();
private class AcceptThread extends Thread {
public void run() {
BluetoothSocket socket = null;
socket = mmServerSocket.accept();
connected(socket, socket.getRemoteDevice(), mSocketType);
private class ConnectThread extends Thread {
public void run() {
while (true) {
bytes = mmInStream.read(buffer); //read incoming message and send to Handle
mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
}
}
}
BluetoothChat.mHandler(){
switch (msg.what) {
case MESSAGE_READ:
}
8. onOptionsItemSelected() //start the char service as a client
switch (item.getItemId()) {case R.id.secure_connect_scan:
serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
return true;
}
onActivityResult(){ // called when the activity to start bluetooth is finished
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
connectDevice(data, true);
break;
}
connectDevice(){
String address = data.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
mChatService.connect(device, secure);
}
9. BluetoothChatService.connect() -- ConnectThread.start() --
-- BluetoothChatService.connected() -- ConnectedThread.start()
public synchronized void connect(){
mConnectThread = new ConnectThread(device, secure);
mConnectThread.start();
setState(STATE_CONNECTING);
}
private class ConnectThread extends Thread {
public void run() {
mmSocket.connect(); // a blocking call returning either a successful connection or an exception
connected(mmSocket, mmDevice, mSocketType);
}
}
//the part of the connected thread is same as server at point 7.
10. Send message
setupChat(){
mSendButton = (Button) findViewById(R.id.button_send);
mSendButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
sendMessage(message);
}
});
}
sendMessage(){
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
//Check that we're actually connected before trying anything
}
if (message.length() > 0) {
//Check that there's actually something to send
}
11. Make bluetooth discoverable
onOptionsItemSelected() {
switch (item.getItemId()) {
case R.id.scan:
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
return true;
case R.id.discoverable:
// Ensure this device is discoverable by others
ensureDiscoverable();
return true;
}
return false;
}
ensureDiscoverable() {
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
key word:
synchronized function:When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.