Android -BLE Bluetooth module development

Android-Ble Bluetooth Development Demo Example-Scanning, Connecting, Sending and Receiving Data, Subpackaging and Unpacking (with Source Code) - Brief Book Preface The Internet of Things era of the Internet of Everything has come, and ble Bluetooth development plays an important role in it. I just have some free time recently, so I took the time to sort out the knowledge points in this area. Clients involved in ble Bluetooth communication (open, scan, connect, send... icon-default.png?t=N7T8https://www.jianshu.com/p/1586f916f3d0 Clients involved in ble Bluetooth communication (open, scan, connect, send and receive data, Subpackage unpacking) and the server (initialize broadcast data, start broadcast, configure Services, Server callback operation) the whole link and some common problems are some pits that have been stepped on.

Bluetooth is divided into traditional (classic) Bluetooth and BLE (Bluetooth Low Energy). The development APIs of the two are different. This article focuses on the development of Ble Bluetooth. Traditional Bluetooth will not be expanded. If you need it, you can learn about it by yourself.

Compared with traditional Bluetooth, BLE low-power Bluetooth is mainly characterized by fast search, fast connection, ultra-low power consumption to maintain connection and data transmission.

ndroid4.3 (API Level 18) began to introduce the core functions of BLE and provided corresponding APIs. Applications use these APIs to scan Bluetooth devices, query services, read and write device characteristics, and other operations.

The BLE Bluetooth protocol is the GATT protocol. There are not many BLE related classes. They are all located in several classes of the android.bluetooth package and android.bluetooth.le package:
android.bluetooth.
.BluetoothGattService contains multiple Characteristic (attribute characteristic values), including unique UUID as an identifier
. BluetoothGattCharacteristic contains a single value and multiple Descriptors, containing a unique UUID as an identifier
. BluetoothGattDescriptor describes the Characteristic, and contains a unique UUID as an identifier.

.BluetoothGatt client related.BluetoothGattCallback
client connection
callback.BluetoothGattServer server related.BluetoothGattServerCallback
server connection callback

android.bluetooth.le.
.AdvertiseCallback The broadcast callback of the server
. AdvertiseData The broadcast data of the server
. AdvertiseSettings The broadcast settings of the server
. BluetoothLeAdvertiser The broadcast of the server

.BluetoothLeScanner Client scan related (Android5.0 new)
.ScanCallback Client scan
callback.ScanFilter Client scan filter.ScanRecord Client
scan result broadcast data.ScanResult
Client scan result.ScanSettings
Client scan settings

BLE devices are divided into two types of devices: client (also called host/central device/Central), server (also called slave/peripheral device/peripheral). The core class of the client is BluetoothGatt. The core class of the server is BluetoothGattServer and
BluetoothLeAdvertiser
BLE
data The core classes are BluetoothGattCharacteristic and BluetoothGattDescriptor

The following explains in detail the development steps of the client and server.

1. BLE client development process

1. Apply for permission

Android phones involve Bluetooth permission issues. Bluetooth development needs to add a permission statement in the AndroidManifest.xml file:

<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
为适配安卓6.0以及以上版本需要添加一个模糊定位的权限
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
手机权限管理中允许此权限,否则会出现无法搜索到设备的情况;

BLE权限增加了BEL支持检查
(1).在manifest中添加权限
<!-- true 表示手机必须支持BLE,否则无法安装!
    这里设为false, 运行后在Activity中检查-->
<uses-feature
    android:name="android.hardware.bluetooth_le"
    android:required="false" />

(2).在Activity中设置蓝牙
// 检查是否支持BLE蓝牙
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
    Util.toast(this, "本机不支持低功耗蓝牙!");
    finish();
    return;
}

2. Turn on Bluetooth

Before searching for devices, you need to ask to turn on the phone's Bluetooth:

//获取系统蓝牙适配器管理类
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 询问打开蓝牙
if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, 1);
}
  // 申请打开蓝牙请求的回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1) {
        if (resultCode == RESULT_OK) {
            Toast.makeText(this, "蓝牙已经开启", Toast.LENGTH_SHORT).show();
        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(this, "没有蓝牙权限", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

3. Search equipment

Note: The BLE device address changes dynamically (changes every once in a while), while the classic Bluetooth device is fixed at the factory!

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 下面使用Android5.0新增的扫描API,扫描返回的结果更友好,比如BLE广播数据以前是byte[] scanRecord,而新API帮我们解析成ScanRecord类\
final BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
bluetoothLeScanner.startScan(mScanCallback);
mHandler.postDelayed(new Runnable() {
    @Override
    public void run() {
        bluetoothLeScanner.stopScan(mScanCallback); //停止扫描
        isScanning = false;
    }
}, 3000);

// 扫描结果Callback
private final ScanCallback mScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {、
        BluetoothDevice dev = result.getDevice() 获取BLE设备信息
        // result.getScanRecord() 获取BLE广播数据
    }
};

// 旧API是BluetoothAdapter.startLeScan(LeScanCallback callback)方式扫描BLE蓝牙设备,如下:
mBluetoothAdapter.startLeScan(callback);
private LeScanCallback callback = new LeScanCallback() {
    @Override
    public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
        //device为扫描到的BLE设备
        if(device.getName() == "目标设备名称"){
            //获取目标设备
            targetDevice = device;
        }
    }
};

4. Connect the device

By scanning the BLE device, the target device targetDevice is distinguished according to the device name. The next step is to connect to the target device. Stop searching for Bluetooth before connecting to the device. Stopping the search generally takes a certain amount of time to complete. It is best to call the stop search function and then add it. The 100ms delay ensures that the system can completely stop searching for Bluetooth devices. Start the connection process after stopping the search;

The connection method of BLE Bluetooth is relatively simple, just call the connectGatt method;

public BluetoothGatt connectGatt (Context context, boolean autoConnect, BluetoothGattCallback callback);

Parameter Description

  • Return value BluetoothGatt: BLE Bluetooth connection management class, mainly responsible for communicating with the device;
  • boolean autoConnect: It is recommended to set it to false to improve the connection speed;
  • BluetoothGattCallback callback connection callback, important parameters, the core part of BLE communication;

5. Device communication

After establishing a connection with the device and communicating with the device, the entire communication process is completed in the asynchronous callback function of BluetoothGattCallback;

The main callback functions in BluetoothGattCallback are as follows:

private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {

    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {
        //连接状态改变的Callback
    }
    
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        //服务发现成功的Callback
    }
    
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {
        //写入Characteristic
    }
    
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
         //读取Characteristic 
     }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {
        //通知Characteristic
    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        //写入Descriptor
    }
  
    @Override
    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        //读取Descriptor
    }
       
};

The above callback functions are indispensable in BLE development;

6. Wait for the device to connect successfully

After calling targetdDevice.connectGatt(context, false, gattCallback), the system will actively initiate a connection with the BLE Bluetooth device. If it is successfully connected to the device, it will call back the onConnectionStateChange method. The processing process is as follows:

@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {
     if (newState == BluetoothGatt.STATE_CONNECTED) {
         Log.e(TAG, "设备连接上 开始扫描服务");
         // 连接成功后,开始扫描服务
         mBluetoothGatt.discoverServices();
     }
     if (newState == BluetoothGatt.STATE_DISCONNECTED) {
         // 连接断开
         /*连接断开后的相应处理*/      
     }
};

Judging that newState == BluetoothGatt.STATE_CONNECTED indicates that it has successfully connected to the device at this time;

7. Start scanning service

mBluetoothGatt.discoverServices();

Scanning BLE device services is an important step in the development of BLE Bluetooth in the Android system. It is generally called after the device is successfully connected. After scanning the device service, the onServicesDiscovered() function is called back. The function prototype is as follows:

@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
    private List<BluetoothGattService> servicesList;
    //获取服务列表
    servicesList = mBluetoothGatt.getServices();
}
  • The data communication method under the BLE Bluetooth protocol uses three main classes: BluetoothGattService, BluetoothGattCharacteristic and BluetoothGattDescriptor to realize communication;
  • BluetoothGattService, short for service, is a component unit that constitutes the BLE device protocol stack. A Bluetooth device protocol stack generally consists of one or more BluetoothGattServices;
  • BluetoothGattCharacteristic is short for feature, a service contains one or more features, and features are the basic unit of data;
  • A BluetoothGattCharacteristic characteristic contains a data value and an additional description about the characteristic;
  • BluetoothGattDescriptor: A class used to describe characteristics, which also contains a value;

8. Obtain the BluetoothGattCharacteristic responsible for communication

BLE Bluetooth development is mainly completed by BluetoothGattService, which is responsible for communication. It is also called a communication service. Communication services are obtained through the UUID provided by the hardware engineer. How to get it:

  • BluetoothGattService service = mBluetoothGatt.getService(UUID.fromString("UUID string provided by the Bluetooth module responsible for communication"));
  • The communication service includes BluetoothGattCharacteristic, which is responsible for reading and writing, and are called notifyCharacteristic and writeCharacteristic respectively. Among them, notifyCharacteristic is responsible for opening monitoring, that is, starting the channel for receiving data, and writeCharacteristic is responsible for writing data;

The specific operation method is as follows:

  BluetoothGattService service = mBluetoothGatt.getService(UUID.fromString("蓝牙模块提供的负责通信服务UUID字符串"));
   // 例如形式如:49535343-fe7d-4ae5-8fa9-9fafd205e455
  notifyCharacteristic = service.getCharacteristic(UUID.fromString("notify uuid"));
  writeCharacteristic =  service.getCharacteristic(UUID.fromString("write uuid"));

9. Turn on monitoring

Turning on monitoring means establishing the first data channel for communication with the device. In BLE development, only when the client successfully turns on monitoring can it send and receive data with the server. The way to turn on monitoring is as follows:

mBluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true)
BluetoothGattDescriptor descriptor = characteristic .getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
//若开启监听成功则会回调BluetoothGattCallback中的onDescriptorWrite()方法,处理方式如下:
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
   if (status == BluetoothGatt.GATT_SUCCESS) {
       //开启监听成功,可以向设备写入命令了
       Log.e(TAG, "开启监听成功");
   }
};

10. Write data

The amount of data written by BLE at a time is limited, usually 20 bytes . You can try to increase it through the requestMTU, but there is no guarantee of success. Sub-packet writing is a solution. It is necessary to define a sub-packet protocol. Assuming that each package is 20 bytes in size, there are two types of packets, data packets and non-data packets. For data packets, the first two bytes represent the sequence number of the packet, and the rest are filled with data. For non-data packets, it is mainly to send some control information.
After successful monitoring, communicate with the server by writing data to writeCharacteristic. The writing method is as follows:

//value为客户端向服务端发送的指令
writeCharacteristic.setValue(value);
mBluetoothGatt.writeCharacteristic(writeCharacteristic)

Among them: value is generally a Hex format instruction, and its content is specified by the Bluetooth communication protocol of device communication;

11. Receive data

If the write command is successful, call back the onCharacteristicWrite() method in BluetoothGattCallback, indicating that the data has been sent to the lower computer;

@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
    BluetoothGattCharacteristic characteristic, int status) {
    if (status == BluetoothGatt.GATT_SUCCESS) {
        Log.e(TAG, "发送成功");
    }
}

If the data sent complies with the communication protocol, the server will reply to the client with corresponding data. The data sent is obtained through the callback onCharacteristicChanged() method, which is processed as follows:

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
    // value为设备发送的数据,根据数据协议进行解析
    byte[] value = characteristic.getValue();
}

By sending instructions to the server to obtain the server's reply data, the communication process with the device can be completed;

12. Disconnect

After completing communication with the device, be sure to disconnect from the device. Call the following method to disconnect from the device:

mBluetoothGatt.disconnect();
mBluetoothGatt.close();

2. BLE server development process

1. Set broadcast and initialize broadcast data

//广播设置(必须)
AdvertiseSettings settings = new AdvertiseSettings.Builder()
        .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) //广播模式: 低功耗,平衡,低延迟
        .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) //发射功率级别: 极低,低,中,高
        .setTimeout(0)
        .setConnectable(true) //能否连接,广播分为可连接广播和不可连接广播
        .build();

//广播数据(必须,广播启动就会发送)
AdvertiseData advertiseData = new AdvertiseData.Builder()
        .setIncludeDeviceName(true) //包含蓝牙名称
        .setIncludeTxPowerLevel(true) //包含发射功率级别
        .addManufacturerData(1, new byte[]{23, 33}) //设备厂商数据,自定义
        .build();

//扫描响应数据(可选,当客户端扫描时才发送)
AdvertiseData scanResponse = new AdvertiseData.Builder()
        .addManufacturerData(2, new byte[]{66, 66}) //设备厂商数据,自定义
        .addServiceUuid(new ParcelUuid(UUID_SERVICE)) //服务UUID
//                .addServiceData(new ParcelUuid(UUID_SERVICE), new byte[]{2}) //服务数据,自定义
        .build();

2. Start broadcasting

BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
//BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

// ============启动BLE蓝牙广播(广告) ===============
mBluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
mBluetoothLeAdvertiser.startAdvertising(settings, advertiseData, scanResponse, mAdvertiseCallback);

// BLE广播Callback
private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
    @Override
    public void onStartSuccess(AdvertiseSettings settingsInEffect) {
        logTv("BLE广播开启成功");
    }

    @Override
    public void onStartFailure(int errorCode) {
        logTv("BLE广播开启失败,错误码:" + errorCode);
    }
};

3. Configure Services and Characteristic

// 注意:必须要开启可连接的BLE广播,其它设备才能发现并连接BLE服务端!
// =============启动BLE蓝牙服务端======================================
BluetoothGattService service = new BluetoothGattService(UUID_SERVICE, BluetoothGattService.SERVICE_TYPE_PRIMARY);

//添加可读+通知characteristic
BluetoothGattCharacteristic characteristicRead = new BluetoothGattCharacteristic(UUID_CHAR_READ_NOTIFY,BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ);
characteristicRead.addDescriptor(new BluetoothGattDescriptor(UUID_DESC_NOTITY, BluetoothGattCharacteristic.PERMISSION_WRITE));
service.addCharacteristic(characteristicRead);

//添加可写characteristic
BluetoothGattCharacteristic characteristicWrite = new BluetoothGattCharacteristic(UUID_CHAR_WRITE, BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_WRITE);
service.addCharacteristic(characteristicWrite);

if (bluetoothManager != null){
    mBluetoothGattServer = bluetoothManager.openGattServer(this, mBluetoothGattServerCallback);
}

mBluetoothGattServer.addService(service);

4. Server callback and operation

/**
* 服务事件的回调
*/
private BluetoothGattServerCallback mBluetoothGattServerCallback= new BluetoothGattServerCallback() {

   /**
    * 1.连接状态发生变化时
    */
   @Override
   public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
       Log.e(TAG, String.format("1.onConnectionStateChange:device name = %s, address = %s", device.getName(), device.getAddress()));
       Log.e(TAG, String.format("1.onConnectionStateChange:status = %s, newState =%s ", status, newState));
   }

   @Override
   public void onServiceAdded(int status, BluetoothGattService service) {
       Log.e(TAG, String.format("onServiceAdded:status = %s", status));
   }

   @Override
   public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
       Log.e(TAG, String.format("onCharacteristicReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
       Log.e(TAG, String.format("onCharacteristicReadRequest:requestId = %s, offset = %s", requestId, offset));

       mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
   }

   /**
    * 3. onCharacteristicWriteRequest,接收具体的字节
    */
   @Override
   public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] requestBytes) {
       Log.e(TAG, String.format("3.onCharacteristicWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
       Log.e(TAG, String.format("3.onCharacteristicWriteRequest:requestId = %s, preparedWrite=%s, responseNeeded=%s, offset=%s, value=%s", requestId, preparedWrite, responseNeeded, offset, requestBytes.toString()));
       mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, requestBytes);
       
       //4.处理响应内容
       onResponseToClient(requestBytes, device, requestId, characteristic);
   }

   /**
    * 2.描述被写入时,在这里执行 bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS...  收,触发 onCharacteristicWriteRequest
    */
   @Override
   public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
       Log.e(TAG, String.format("2.onDescriptorWriteRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
       Log.e(TAG, String.format("2.onDescriptorWriteRequest:requestId = %s, preparedWrite = %s, responseNeeded = %s, offset = %s, value = %s,", requestId, preparedWrite, responseNeeded, offset, value.toString()));

       // now tell the connected device that this was all successfull
       mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
   }

   /**
    * 5.特征被读取。当回复响应成功后,客户端会读取然后触发本方法
    */
   @Override
   public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
       Log.e(TAG, String.format("onDescriptorReadRequest:device name = %s, address = %s", device.getName(), device.getAddress()));
       Log.e(TAG, String.format("onDescriptorReadRequest:requestId = %s", requestId));

       mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null);
   }

   @Override
   public void onNotificationSent(BluetoothDevice device, int status) {
       super.onNotificationSent(device, status);
       Log.e(TAG, String.format("5.onNotificationSent:device name = %s, address = %s", device.getName(), device.getAddress()));
       Log.e(TAG, String.format("5.onNotificationSent:status = %s", status));
   }

   @Override
   public void onMtuChanged(BluetoothDevice device, int mtu) {
       super.onMtuChanged(device, mtu);
       Log.e(TAG, String.format("onMtuChanged:mtu = %s", mtu));
   }

   @Override
   public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
       super.onExecuteWrite(device, requestId, execute);
       Log.e(TAG, String.format("onExecuteWrite:requestId = %s", requestId));
   }
};

/**
* 4.处理响应内容
*
* @param reqeustBytes
* @param device
* @param requestId
* @param characteristic
*/
private void onResponseToClient(byte[] reqeustBytes, BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic) {
   Log.e(TAG, String.format("4.onResponseToClient:device name = %s, address = %s", device.getName(), device.getAddress()));
   Log.e(TAG, String.format("4.onResponseToClient:requestId = %s", requestId));
   Log.e(TAG, "4.收到:");

   String str = new String(reqeustBytes) + " hello>";
   characteristicRead.setValue(str.getBytes());
   mGattServer.notifyCharacteristicChanged(device, characteristicRead, false);

   Log.i(TAG, "4.响应:" + str);
   MainActivity.handler.obtainMessage(MainActivity.DEVICE, new     String(reqeustBytes)).sendToTarget();
}

3. Source code download

The source code is uploaded on CSDN, and you can learn from it if you need it.

=====> Android Bluetooth Ble communication Demo sample source code – scanning, connecting, sending and receiving data, sub-packaging and unpacking

4. Precautions for Bluetooth operation

1. How to avoid 133 error in ble Bluetooth connection?

  • Android has a limited number of connected peripheral devices. When there is no need to connect to a Bluetooth device, the BluetoothGatt#close method must be called to release resources;
  • The timeout time for Bluetooth API to connect to a Bluetooth device is about 20s. The specific time depends on the system implementation. Sometimes it takes a long time for some devices to connect via Bluetooth, about ten seconds. If you manually set the connection timeout on some devices, it may cause the next few connection attempts to return state == 133 in BluetoothGattCallback#onConnectionStateChange;
  • Can you avoid errors such as 133 reported when the Android device is connected/disconnected from the ble device?
    1. After the connection fails or is disconnected, call close and refresh the cache.
    2. Try not to try to connect when startLeScan, stopLeScan first and then Reconnect
    3. Disconnect the same device and connect again (reconnect after connection failure). Even after calling close, you need to wait for a while (tried once at 400 milliseconds, but the result did not work; after 1000 milliseconds, there was no problem again). Then go to connectGatt
    4. You can startLeScan before connecting, the success rate is higher

2. The data size written in a single time is limited to 20 bytes. How to send long data?

There is a limit to the amount of data that BLE can write at a time, usually 20 bytes. You can try to increase it through requestMTU, but success is not guaranteed. Subpackaging writing is a solution that requires defining a subpackaging protocol. Assume that each packet is 20 bytes in size and divided into two types of packets, data packets and non-data packets. For data packets, the first two bytes represent the sequence number of the packet, and the rest are filled with data. For non-data packets, some control information is mainly sent.
The overall process is as follows:
1. Define the communication protocol as follows (this is just an example and can be expanded according to project needs)

Message number (1 byte) Function (1 byte) Subfunction (1 byte) Data length (2 bytes) Data content (N bytes) CRC check (1 byte)
01 01 01 0000 -- 2D

2. Encapsulate the universal sending data interface (unpacking).
This interface splits the data to be sent according to the maximum number of bytes (usually 20 bytes) and puts it into the queue. After splitting, it is taken out of the queue and sent in turn.

3. Encapsulate the universal receiving data interface (packaging).
This interface parses the data length according to the definition in the protocol according to the received data and determines whether the package is complete. If not, each message is accumulated.

4. Parse the complete data packet and perform business logic processing

5. The protocol can also introduce encryption and decryption. When selecting algorithm parameters, you need to pay attention to the fact that the encrypted length should be consistent with the original data length, so that it will not affect the unpacking and grouping.

3. Bluetooth devices cannot be scanned on different Android versions or different mobile phones.

Generally, it is a matter of Android version adaptation and permission issues of different ROM models (Xiaomi/Redmi, Huawei/Honor, etc.) (EMUI, MIUI, ColorOS, etc.)

4. Others

  • Bluetooth write and read operations must be serialized. Writing data and reading data cannot be performed at the same time. If the method of writing data is called, immediately call and call the method of writing data or reading data. The method called for the second time will immediately return false, which means that the operation cannot be performed currently;

Guess you like

Origin blog.csdn.net/qq_25462179/article/details/132698100