Overview
I learned some knowledge about Bluetooth development some time ago and recorded the simple development of Bluetooth in Android. Below are the two most important categories.
BluetoothAdapter: Bluetooth adapter, get an instance through getDefaultAdapter (). If the device does not support Bluetooth, it returns a null object. Through it, Bluetooth can be turned on and off, scan the device, and create a socket channel to the specified device...
BluetoothDevice: Represents a device object, through which the device's name, address, type, etc. can be obtained, or matches can be created, socket channels can be established, etc.
1. Authorization application
<uses-permission android:name=""/> Permissions required to use Bluetooth <uses-permission android:name=".BLUETOOTH_ADMIN"/> Use Scan and Set Bluetooth Permissions(Declare this permission must declare the above permission)
Android 6 or above, scanning for other Bluetooth requires location permissions
// Android 9 and below<user-permission android:name=".ACCESS_COARSE_LOCATION"/> // Android 9 or above<uses-permission android:name=".ACCESS_FINE_LOCATION"/>
2. Turn on Bluetooth
mBluetoothAdapter = (); // If the device does not support Bluetoothif (mBluetoothAdapter == null){ return; } // The device supports Bluetooth function, call startActivityForResult to start Bluetoothif (!()){ (new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)); }
Turning on the Bluetooth function is started through startActivity, but the startActivity function has expired, so I used the official recommended Activity Result to replace it
ActivityResultLauncher<Intent> startBlueTooth = registerForActivityResult(new (), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result==null){ (, "open failed", Toast.LENGTH_SHORT).show(); }else { if (() == RESULT_CANCELED){ (,"User Cancel",Toast.LENGTH_SHORT); } } } });
3. Changes in the status of the Bluetooth received
Receive Bluetooth status changes through broadcast
class BluetoothStateChangeReceiver extends BroadcastReceiver{ public int DEFAULT_VALUE_BLUETOOTH = 1000; @Override public void onReceive(Context context, Intent intent) { String action = (); if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){ int state = (BluetoothAdapter.EXTRA_STATE,DEFAULT_VALUE_BLUETOOTH); switch(state){ case BluetoothAdapter.STATE_ON: (TAG, "onReceive: open"); break; case BluetoothAdapter.STATE_OFF: (TAG, "onReceive: off"); break; case BluetoothAdapter.STATE_TURNING_ON : (TAG, "onReceive: Opening"); break; case BluetoothAdapter.STATE_TURNING_OFF: (TAG, "onReceive: Closed"); break; } } } }
Don't forget the registration and settlement of broadcast
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); stateReceiver = new BluetoothStateChangeReceiver() ; registerReceiver(stateReceiver,filter);
4. Scan other devices
Also received through broadcast, the action is BluetoothDevice.ACTION_FOUND
class MyReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { String action = (); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get information about Bluetooth devices from intent object BluetoothDevice device = (BluetoothDevice.EXTRA_DEVICE); // Added when a new device is found not exists in the pairing list if (() != BluetoothDevice.BOND_BONDED) { (()+"\t"+()); } (); (TAG, "onReceive: " + ()); } } }
Dynamic registration of broadcast
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mReceiver,filter);
Turn on scanning
();
5. Bluetooth pairing
public class BondReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(())){ BluetoothDevice device = (BluetoothDevice.EXTRA_DEVICE); switch(()){ case BluetoothDevice.BOND_BONDED: (TAG, "onReceive: Pairing Completed"); break; case BluetoothDevice.BOND_BONDING: (TAG, "onReceive: Pairing"); break; case BluetoothDevice.BOND_NONE: (TAG, "onReceive: Unpair"); break; } } } }
6. Obtain the paired device
The paired devices will be stored and can be directly obtained through BluetoothAdpater
Set<BluetoothDevice> paireDevices = (); if (()>0){ for (BluetoothDevice pairedDevice : pairedDevices) { (()+" "+()); (TAG, "onClick: "+()); } }
7. Connect to the device
To create a connection between two devices, the client and server mechanism must be implemented. They use the socket mechanism to connect. The server opens the server socket, and the client initiates the connection to the server through the MAC address. Clients and servers are obtained in different waysBluetoothSocket
,When the client and the server have connected on the same RFCOMM channelBluetoothSocket
When they are considered to be connected to each other, each device gets input and output streaming and starts transmitting data.
Connection technology
One implementation technique is to automatically prepare each device as a server, so that each device opens a service socket and listens for connections, in which case any device can initiate a connection to another device and be called a client.
server
Set up the server socket and accept the connection. The steps are as follows
1. Call listenUsingRfcommWithServiceRecord() to get aBluetoothServerSocket
, This function requires two parameters. The first is the name of the server, you can just take one by yourself, and the second is the UUID, which is used to uniquely identify the information. We can randomly generate one from many UUID generators on the Internet, and then initialize a UUID using (String).
2. Start listening to connection requests through the accept() function
The server will only accept the request if the UUID in the connection request sent by the remote device matches the UUID registered with this socket. The accept function will return the connected one.BluetoothSocket
3. Called after the connection is successfulclose()
Close BluetoothSocket
private class AcceptThread extends Thread{ private final BluetoothServerSocket mmServerSocket; private String mSocketType; public AcceptThread(boolean secure){ BluetoothServerSocket tmp = null; mSocketType = secure ? "secure" : "Insercure"; try{ if (secure){ tmp = (NAME_SECURE,MY_UUID_SECURE); }else{ tmp = (NAME_INSECURE,MY_UUID_INSECURE); } } catch (IOException e) { (TAG,"socket type"+ mSocketType + "listen() failed",e); } mmServerSocket = tmp; } @Override public void run() { (TAG, "Socket Type: " + mSocketType + "BEGIN mAcceptThread" + this); setName("AcceptThread"+ mSocketType); BluetoothSocket socket = null; (TAG, "run: Start listening"); while (true){ try{ socket = (); ("acceptThread", "run: Connection successful"); connected(socket,(),mSocketType); } catch (IOException e) { (TAG, "Socket Type: " + mSocketType + "accept() failed", e); break; } } (TAG, "END mAcceptThread, socket Type: " + mSocketType); } public void cancel() { (TAG, "Socket Type" + mSocketType + "cancel " + this); try { (); } catch (IOException e) { (TAG, "Socket Type" + mSocketType + "close() of server failed", e); } } }
The above secure and Insecure just use different UUIDs.
Client
After the remote device is turned on listening, we initiate a connection to this device. First, we must first obtain the BluetoothDevice object of the remote device, and then obtain the BluetoothSocket initiates the connection.
The basic steps are as follows
1. UseBluetoothDevice
By callingcreateRfcommSocketToServiceRecord(UUID)
GetBluetoothSocket
。
2. Start a connection through connect
private class ConnectThread extends Thread{ private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; private String mSocketType; public ConnectThread(BluetoothDevice device, boolean secure){ mmDevice = device; BluetoothSocket tmp = null; mSocketType = secure ? "Secure" : "Insecure"; try { if (secure){ tmp = (MY_UUID_SECURE); }else { tmp = (MY_UUID_INSECURE); } } catch (IOException e) { (TAG, "Socket Type: " + mSocketType + "create() failed", e); } mmSocket = tmp; } @Override public void run() { (TAG, "BEGIN mConnectThread SocketType:" + mSocketType); setName("ConnectThred"+mSocketType); // Always cancel discovery because it slows down the connection (); // connect // Make a connection to the BluetoothSocket try { // This is a blocking call and will only return on a // successful connection or an exception (); (TAG, "run: socket connection is successful"); } catch (IOException e) { // Close the socket (TAG, "run: close socket"); try { (); } catch (IOException e2) { (TAG, "unable to close() " + mSocketType + " socket during connection failure", e2); } return; } connected(mmSocket,mmDevice,mSocketType); } public void cancel(){ try{ (); } catch (IOException e) { (TAG, "close() of connect " + mSocketType + " socket failed", e); } } }
Send data
After the connection is successful, we can send data through the socket. The client's Socket object isBluetoothSocket
The server socket isBluetoothServerSocket
, be careful not to confuse it. usegetInputStream
andgetOutputStream
Get data transmissions through sockets separatelyInputStream
andOutputStream
. Writing data is relatively simple, but reading data requires a separate thread to keep listening.
private class ConnectedThread extends Thread{ private final BluetoothSocket mmSocket; private InputStream mmInStream; private OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket, String socketType) throws IOException { (TAG, "create ConnectedThread: " + socketType); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; try{ tmpIn = (); tmpOut = (); if (socket != null){ (new String("hello").getBytes()); (TAG, "ConnectedThread: socket is not null"); } } catch (IOException e) { (TAG,"temp socket not created", e); } mmInStream = tmpIn; mmOutStream = tmpOut; // (new String("hello").getBytes()); } @RequiresApi(api = Build.VERSION_CODES.KITKAT) @Override public void run() { (TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[1024]; int bytes; while (true){ try{ bytes = (buffer); // send the bytes to the ui Activity String text = encodeByteToString(buffer,bytes); (TAG, "run: Received the message:"+ text); (text); (()); } catch (IOException e) { (TAG, "run: No message received"); (); break; } } } public String encodeByteToString(byte[] data,int length) { byte[] temp = new byte[length]; for (int i = 0; i < length; i++) { temp[i] = data[i]; } try { return new String(temp,"utf-8"); } catch (UnsupportedEncodingException e) { return ""; } } public void write(byte[] buffer){ try{ (buffer); // (Constants.MESSAGE_WRITE,-1,-1,buffer).sendToTarget(); } catch (IOException e) { (); } } public void cancel(){ try{ (); (TAG, "cancel: connectedThread"); } catch (IOException e) { (TAG, "close() of connect socket failed", e); } } }
In the example above, I mainly learn the code written by Bluetooth chat projects on the official website. You can also directly read the official website projects. From the above example, we can see that the received data streams are all binary, and some encoding and conversion are required to be used in actual projects. That is, I write some protocols myself. Students who have studied socket programming must understand it. In fact, Bluetooth already has many useful protocols, such as AVRCP (Audio Video Remote Control Profile), which defines the characteristics and processes of communication between Bluetooth devices and audio/video control functions. Combined with MediaSession, the audio and video control of the device can be easily realized.
This is the end of this article about the simple development sample tutorial of Android Bluetooth. For more related content on Android Bluetooth development, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!