In depth analysis of Android bluetooth development
- 2020-05-17 06:31:08
- OfStack
1. Use the response permission of bluetooth
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
2. Configure the native bluetooth module
The first step here is to understand the operation of bluetooth 1 core class BluetoothAdapter
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
// Directly open the system's bluetooth Settings panel
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 0x1);
// Turn on bluetooth directly
adapter.enable();
// Close the bluetooth
adapter.disable();
// Turn on bluetooth discovery on the device (enabled by default) 120 Second, can be extended to the maximum time 300 A second)
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);// Set the duration (maximum) 300 A second)
3. Search for bluetooth devices
Search for bluetooth devices using the startDiscovery() method of BluetoothAdapter
The startDiscovery() method is an asynchronous method that returns immediately after the call. The method searches for other bluetooth devices for 12 seconds. After this method is called, the search is actually done in an System Service, so you can call the cancelDiscovery() method to stop the search (which can be called when an discovery request is not executed).
After requesting Discovery, the system searches for the bluetooth device. During this process, the system sends the following three broadcasts:
ACTION_DISCOVERY_START: start the search
ACTION_DISCOVERY_FINISHED: end of search
ACTION_FOUND: find the device, this Intent contains two extra fields: EXTRA_DEVICE and EXTRA_CLASS, BluetooDevice and BluetoothClass, respectively.
We can register the corresponding BroadcastReceiver to receive the broadcast response, so as to achieve certain functions
// create 1 A receiving ACTION_FOUND The radio BroadcastReceiver
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// Find equipment
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// from Intent Gets the device object in
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Put the device name and address in array adapter In order to ListView Shown in the
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// registered BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unbind later
4. Bluetooth Socket communication
If you intend to suggest a connection between two bluetooth devices, you must implement a server-side and client-side mechanism. When two devices have one BluetoothSocket connected under the same RFCOMM channel, the two devices can be said to have established a connection.
The way the server device and the client device get BluetoothSocket is different. The server device is obtained by accepted1 incoming connection, while the client device is obtained by opening 1 RFCOMM channel to the server.
Server-side implementation
Get BluetoothServerSocket (UUID for matching between client and server) by calling the listenUsingRfcommWithServiceRecord(String, UUID) method of BluetoothAdapter
Call BluetoothServerSocket's accept() method to listen for connection requests, and if a request is received, return an instance of BluetoothSocket (this method is the block method and should be placed in a new thread)
If you do not want another connection in accept, call BluetoothServerSocket's close() method to free up the resource (after calling this method, the previously obtained BluetoothSocket instance does not have close. However, since RFCOMM1 only allows 1 connection in 1 channel at a time, close will drop BluetoothServerSocket after 1 connection in accept1.)
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) { }
}
}
Client implementation
Search for BluetoothService on the server side
Call BluetoothService's listenUsingRfcommWithServiceRecord(String, UUID) method to get BluetoothSocket (this UUID should be the same as UUID on the server side)
Call the connect() method of BluetoothSocket, which is the block method. If UUID matches UUID on the server side and the connection is made to accept on the server side, the connect() method returns
Note: before calling the connect() method, make sure there is no current search device, or the connection will become very slow and fail easily
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) { }
}
}
Connection management (data communication)
InputStream and OutputStream were obtained by getInputStream() and getOutputStream() methods of BluetoothSocket, respectively
Read and write operations are performed using the read(bytes[]) and write(bytes[]) methods, respectively
Note: the read(bytes[]) method will direct block until information is read from the stream, while the write(bytes[]) method will not often block (e.g., write will block if another device fails to read in time or the intermediate buffer is full).
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) { }
}
}
Official Android SDK, Android/OPhone notes for full development