The article directories

      • The development process
      • permissions
      • Core API
        • BlueToothAdapter
          • GetDefaultAdapter (): Gets the BluetoothAdapter object
          • Check whether the device supports Bluetooth
          • Check whether bluetooth is enabled
          • getBondedDevices()
          • isDiscovering()
          • cancelDiscovery()
          • startDiscovery()
          • getAddress() | getName() | getState()
        • BluetoothDevice
          • getAddress() | getName() | getState()
      • Function implementation
        • Scan the bluetooth
          • Start scanning
          • Receive the scan result in broadcast mode
            • Registration of radio
            • Receive the broadcast
        • Pairing bluetooth
          • Pairing specified devices
          • Cancel the pairing
          • Receive match results by broadcast
        • Bluetooth connection
          • Bluetooth connection thread
          • Start the connection thread
          • Check whether the connection is successful
          • disconnect

The development process

  • Open the bluetooth
  • Scan for Bluetooth and add these devices to the devices list
  • Pairing bluetooth adds the secondary device to the list of paired devices
  • Connect the bluetooth
  • communication

Some explanation

Device list: indicates the nearby bluetooth devices that are visible but have not been matched. Matched device list: indicates the list that has been matched

The device types are as follows: unmatched, Matched, and Paired.

Unmatched: indicates that the device is in the matching state that has never been matched. It indicates that the devices have completed the authentication of each other and are in the state to be paired (Socket to be established)

In the past, when bluetooth was paired, the phone would pop up a dialog box asking you to enter a PIN number, which was essentially an agreed matching code. Later, the connection between the phone and the phone would no longer require a matching code (in fact, the pairing process was done internally).

Of course, when the phone is paired with some Bluetooth hardware (such as a combination of microcontroller and Bluetooth module), you still need to enter a PIN code (though this can be verified automatically by the program).

The pairing process is actually a process of Socket communication. Data cannot be transmitted between two Bluetooth devices only when they match. Data can be transmitted only after they establish Socket channels

permissions

<! - use a BLUETOOTH permissions - > < USES - permission android: name = "android. Permission. BLUETOOTH" / > <! - scan bluetooth device or operating the bluetooth Settings - > < USES - permission android: name = "android. Permission. BLUETOOTH_ADMIN" / > <! - the fuzzy positioning permissions, only applies to 6.0 + - > < USES - permission android: name = "android. Permission. ACCESS_COARSE_LOCATION" / > <! - precise permissions, only applies to 6.0 + - > < USES - permission android: name = "android. Permission. ACCESS_FINE_LOCATION" / >Copy the code

If the BroadcastReceiver does not register for the BroadcastReceiver to listen to the BroadcastReceiver scan results, it will not be successful

Core API

Android bluetooth development involves different kinds of bluetooth, such as low power bluetooth (BluetoothGatt), BlueToothHealth (BlueToothHealth), and so on, here is still a routine bluetooth development API

BlueToothAdapter

This class represents the native Bluetooth adapter and allows you to perform various Bluetooth-related operations, such as starting and stopping device searches; Query matched devices and return them as collections. Instantiate a BlueToothDevice from a known device address; Creating a BluetoothServerSocket to listen for link requests from other devices and so on, this class is extremely important to use native bluetooth

GetDefaultAdapter (): Gets the BluetoothAdapter object
/ / get the local bluetooth adapter bluetoothAdapter = bluetoothAdapter. GetDefaultAdapter ();Copy the code
Check whether the device supports Bluetooth
/** * whether the device supports bluetooth true: support * @return */ public Boolean isSupportBlue(){return bluetoothAdapter! = null; }Copy the code
Check whether bluetooth is enabled
/ / get BluetoothAdapter object mBluetoothAdapter = BluetoothAdapter. GetDefaultAdapter (); // Check whether the device supports Bluetooth. If the mBluetoothAdapter is empty, it does not. Otherwise support if (mBluetoothAdapter == null) {toast.maketext (this, "this device does not support Bluetooth ", toast.length_short).show(); } else { // If BT is not on, Request that it be enabled. // setupChat() will then be called during onActivityResult MBluetoothAdapter. IsEnabled ()) {/ / request user open Intent enableIntent = new Intent (BluetoothAdapter. ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); } else { getDeviceList(); }}Copy the code

Check whether the request is enabled

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); If (requestCode == REQUEST_ENABLE_BT) {if (resultCode == activity.result_ok) {// Bluetooth is opened Else {// bluetooth is not open toast.maketext (this, "Bluetooth is not on ", toast.length_short).show(); }}}Copy the code
getBondedDevices()

Gets a list of matched devices and returns them as a set

/ * * get has matched equipment * / private void setPairingDevice () {Set < BluetoothDevice > devices = bluetoothAdapter. GetBondedDevices (); If (devices.size() > 0) {for (Iterator<BluetoothDevice> it = devices.iterator(); it.hasNext(); ) { BluetoothDevice btd = it.next(); ```````}}else{// No paired Bluetooth device exists}}Copy the code
isDiscovering()

Checks whether the device is currently being searched, and returns true

cancelDiscovery()

Cancel find device

startDiscovery()

It should be noted here that since search is a time-consuming operation, this method should be called in the thread and used with the broadcast to start the search device. The general call code is as follows:

private void doDiscovery() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if(bluetoothAdapter.isDiscovering()){
                    bluetoothAdapter.cancelDiscovery();
                }
                bluetoothAdapter.startDiscovery();
            }
        }).start();
    }
Copy the code

Note one more detail here: if the current Adapter is looking up, you must stop the current lookup and try again. This is because the lookup takes up a lot of system resources and we need to avoid repeated lookups

getAddress() | getName() | getState()

GetAddress () obtains the local Bluetooth address getName() obtains the local Bluetooth name getState() obtains the current status of the local Bluetooth adapter

BluetoothDevice

This class represents a remote device that allows us to create a connection with another related device or query information about this device, such as name, address, and connection state.

getAddress() | getName() | getState()

GetAddress () obtains the Bluetooth Address of the Address device. GetName () obtains the bluetooth name of the Address device. GetState () obtains the current status of the Bluetooth adapter of the Address device

Function implementation

Scan the bluetooth

Start scanning

This part of the code has been written before

		if (bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
        }
        // Request discover from BluetoothAdapter
        bluetoothAdapter.startDiscovery();
Copy the code
Receive the scan result in broadcast mode
Registration of radio
/ / search began to filter IntentFilter filter1 = new IntentFilter (android. Bluetooth. BluetoothAdapter. ACTION_DISCOVERY_STARTED); / / the end of the search filter IntentFilter filter2 = new IntentFilter (android. Bluetooth. BluetoothAdapter. ACTION_DISCOVERY_FINISHED); IntentFilter filter3 = new IntentFilter(bluetoothdevice.action_found); IntentFilter filer4 = new IntentFilter(bluetoothDevice.action_bond_state_changed); IntentFilter filter5 = new IntentFilter(bluetoothdevice.action_pairing_request) registerReceiver(mFindBlueToothReceiver ,filter1); registerReceiver(mFindBlueToothReceiver ,filter2); registerReceiver(mFindBlueToothReceiver ,filter3); registerReceiver(mFindBlueToothReceiver ,filter4); registerReceiver(mFindBlueToothReceiver ,filter5);Copy the code
Receive the broadcast
// Broadcast receiver, when the remote Bluetooth device is found, Private final BroadcastReceiver mFindBlueToothReceiver = new BroadcastReceiver() {@override public  void onReceive(Context context, Intent intent) { String action = intent.getAction(); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Switch (action){case bluetoothAdapter.action_discovery_started: log. d(TAG, "Start scanning..." ); callBack.onScanStarted(); break; Case bluetoothAdapter.action_DISCOVERY_finished: log. d(TAG, "End scan..." ); callBack.onScanFinished(); break; Case bluetoothDevice.action_found: log. d(TAG, "Found device..." ); callBack.onScanning(device); break; Case BluetoothDevice.ACTION_BOND_STATE_CHANGED: log. d(TAG, "Device binding status changed..." ); callBack.onStateChanged(device); break; }}};Copy the code

Pairing bluetooth

Pairing specified devices

The Boolean value returnValue is true, indicating that the pairing is successful. After the pairing is successful, the PIN code may be entered. The pairing is complete only after the correct PIN code is entered. You can broadcast the match results

/** * Pair bluetooth device */ private void pinTargetDevice(int position) {// Before pairing, stop searching cancelDiscovery(); BluetoothDevice device device = Devicelist. get(position); // Get the BluetoothDevice object to match. if (device.getBondState() ! = BluetoothDevice.BOND_BONDED) {// No pair to pair try {log. d(TAG, "start pairing..." ); Method createBondMethod = BluetoothDevice.class.getMethod("createBond"); Boolean returnValue = (Boolean) createBondMethod.invoke(device); If (returnValue){log. d(TAG, "Pairing successful..." ); ShowToast (" Match successful ") } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }}}Copy the code
Cancel the pairing
Public void cancelPinBule(BluetoothDevice device){log.d (TAG, BluetoothDevice){@bluetam device (BluetoothDevice device){ "attemp to cancel bond:" + device.getName()); try { Method removeBondMethod = device.getClass().getMethod("removeBond"); Boolean returnValue = (Boolean) removeBondMethod.invoke(device); returnValue.booleanValue(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); Log.e(TAG, "attemp to cancel bond fail!" ); }}Copy the code

It doesn’t work. Looks like you can only unpair in system Settings? So what I did was skip the Bluetooth Settings

  startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
Copy the code
Receive match results by broadcast
/** * Broadcast receiver * When a remote Bluetooth device is found, Private final BroadcastReceiver mFindBlueToothReceiver = new BroadcastReceiver() {@override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); switch (action){ ...... Case BluetoothDevice.ACTION_BOND_STATE_CHANGED: log. d(TAG, "Device binding status changed..." ); Switch (device.getBondState()) {case bluetoothDevice.bond_bonding: log.w (TAG, "pairing......") ); break; Case BluetoothDevice.BOND_BONDED: log. w(TAG, "Pairing completed "); break; Case bluetoothDevice.bond_none: log. w(TAG, "unpairing "); default: break; } break; }}};Copy the code

Bluetooth connection

Bluetooth pairing and connection are two different things. A classic Bluetooth connection is the equivalent of a socket connection and is a time-consuming operation, so it should be done in a child thread

Bluetooth connection thread
Public class bluetask extends AsyncTask<BluetoothDevice, Integer, BluetoothSocket> { private BluetoothDevice bluetoothDevice; private ConnectBlueCallBack callBack; public ConnectBlueTask(ConnectBlueCallBack callBack){ this.callBack = callBack; } @Override protected BluetoothSocket doInBackground(BluetoothDevice... bluetoothDevices) { bluetoothDevice = bluetoothDevices[0]; BluetoothSocket socket = null; Try {log. d(TAG," start socket connection,uuid: 00001101-0000-1000-8000-00805f9b34fb "); socket = bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); if (socket ! = null && ! socket.isConnected()){ socket.connect(); }}catch (IOException e){log. e(TAG,"socket connection failed "); try { socket.close(); } catch (IOException e1) { e1.printStackTrace(); Log.e(TAG," failed to close socket "); } } return socket; } @override protected void onPreExecute() {log.d (TAG," start connection "); if (callBack ! = null) callBack.onStartConnect(); } @Override protected void onPostExecute(BluetoothSocket bluetoothSocket) { if (bluetoothSocket ! = null && bluetoothSocket. IsConnected ()) {the d (TAG, "connection success"); if (callBack ! = null) callBack.onConnectSuccess(bluetoothDevice, bluetoothSocket); }else {log. d(TAG," connection failed "); if (callBack ! = null) callback. onConnectFail(bluetoothDevice, "failed connection "); }}}Copy the code
Start the connection thread
Public void connect(BluetoothDevice device, BluetoothDevice, BluetoothDevice, BluetoothDevice, BluetoothDevice, BluetoothDevice) The scan before ConnectBlueCallBack callBack) {/ / connection closed the if (mBluetoothAdapter. IsDiscovering ()) {mBluetoothAdapter. CancelDiscovery (); } new ConnectBlueTask(callBack).execute(device); }Copy the code

ConnectBlueCallBack is an interface used for post-connect callbacks

public interface ConnectBlueCallBack{
        void onStartConnect();
        void onConnectSuccess(BluetoothDevice device,BluetoothSocket bluetoothSocket);
        void onConnectFail(BluetoothDevice device,String string);
    }
Copy the code

So when you actually call the conn method above, pass in a connected device and new the interface you just defined

Connect(device, new ConnectBlueCallBack() {@override public void onStartConnect() {log.w (TAG, "start connecting "); } @Override public void onConnectSuccess(BluetoothDevice device, BluetoothSocket bluetoothSocket) { Log.w( TAG, "Connection successful "); } @override public void onConnectFail(BluetoothDevice device, String String) {log. w(TAG, "connection failed "); }});Copy the code

It’s worth noting that don’t worry if you don’t know the UUID, some common Bluetooth service protocols already have a convention UUID. For example, our connection to the thermal printer is based on the SPP serial communication protocol, and its corresponding UUID is “00001101-0000-1000-8000-00805F9B34Fb”, so a string of numbers above was written by me

Check whether the connection is successful
Public Boolean isConnectBlue(){return mBluetoothSocket! = null && mBluetoothSocket.isConnected(); }Copy the code
disconnect
Public Boolean cancelConnect(){if (mBluetoothSocket! = null && mBluetoothSocket.isConnected()){ try { mBluetoothSocket.close(); } catch (IOException e) { e.printStackTrace(); return false; } } mBluetoothSocket = null; return true; }Copy the code

Refer to the article

【 Part 1 】 Android Bluetooth development – classic Bluetooth detailed development process