You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android BluetoothGattServer向多台已连接设备同步发送数据的解决方案咨询

Android BLE GATT服务端多设备同步发送流数据解决方案

Android原生蓝牙框架未提供和iOS peripheralManager.updateValue 对等的批量设备发送API,可通过以下方案实现需求:

方案1:独立设备发送队列 + 回调驱动分片发送(兼容性最好,全Android版本可用)

为每个已连接设备维护独立的待发送分片队列,重写BluetoothGattServerCallback的onNotificationSent方法,回调触发后立即给对应设备发送下一个分片,不同设备的发送流程互不阻塞,最大化发送效率。
示例代码:

// 每个设备对应一个发送队列
private ConcurrentHashMap<BluetoothDevice, ConcurrentLinkedQueue<byte[]>> deviceSendQueues = new ConcurrentHashMap<>();
// 记录每个设备是否正在等待发送回调
private ConcurrentHashMap<BluetoothDevice, Boolean> deviceIsSending = new ConcurrentHashMap<>();

// 初始化时给新连接的设备创建队列
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
    super.onConnectionStateChange(device, status, newState);
    if (newState == BluetoothProfile.STATE_CONNECTED) {
        mServerActionListener.addDevice(device);
        deviceSendQueues.put(device, new ConcurrentLinkedQueue<>());
        deviceIsSending.put(device, false);
    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
        mServerActionListener.removeDevice(device);
        deviceSendQueues.remove(device);
        deviceIsSending.remove(device);
    }
}

// 批量提交待发送数据给所有设备
public void sendDataToAllDevices(byte[] data, UUID characteristicUuid) {
    // 先按当前协商的MTU分片,一般MTU减3是单包最大载荷
    int mtu = 512; // 可以替换为实际协商的MTU值
    int chunkSize = mtu - 3;
    List<byte[]> chunks = splitDataToChunks(data, chunkSize);
    for (BluetoothDevice device : mDevices) {
        deviceSendQueues.get(device).addAll(chunks);
        // 如果设备当前没在发送,触发发送流程
        if (!deviceIsSending.get(device)) {
            sendNextChunk(device, characteristicUuid);
        }
    }
}

// 给指定设备发送下一个分片
private void sendNextChunk(BluetoothDevice device, UUID characteristicUuid) {
    ConcurrentLinkedQueue<byte[]> queue = deviceSendQueues.get(device);
    if (queue == null || queue.isEmpty()) {
        deviceIsSending.put(device, false);
        return;
    }
    byte[] chunk = queue.poll();
    BluetoothGattCharacteristic characteristic = mGattServer.getService(SERVICE_UUID).getCharacteristic(characteristicUuid);
    characteristic.setValue(chunk);
    boolean confirm = BluetoothUtils.requiresConfirmation(characteristic);
    deviceIsSending.put(device, true);
    mGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
}

// 回调触发后发送下一个分片
@Override
public void onNotificationSent(BluetoothDevice device, int status) {
    super.onNotificationSent(device, status);
    if (status == BluetoothGatt.GATT_SUCCESS) {
        sendNextChunk(device, YOUR_CHARACTERISTIC_UUID);
    }
}

// 数据分片工具方法
private List<byte[]> splitDataToChunks(byte[] data, int chunkSize) {
    List<byte[]> chunks = new ArrayList<>();
    int length = data.length;
    for (int i = 0; i < length; i += chunkSize) {
        int end = Math.min(length, i + chunkSize);
        chunks.add(Arrays.copyOfRange(data, i, end));
    }
    return chunks;
}

方案2:使用BLE L2CAP CoC通道(适合大流数据传输,Android 10及以上支持)

如果你的应用适配Android 10及以上版本,可使用L2CAP面向连接通道(Connection Oriented Channel)传输流数据,该通道原生支持流式传输,不需要手动拆分特征通知,吞吐量远高于特征值通知,且支持多设备同时独立传输。
核心调用API:

// 服务端开启L2CAP通道
int psm = mBluetoothManager.openL2capServer(/* 加密/传输参数 */);
// 客户端连接对应PSM即可获得输入输出流,直接读写流数据

方案3:使用无响应通知批量提交(Android 12及以上优化)

如果你使用的是不需要确认的NOTIFICATION类型(confirm = false),Android 12及以上版本的蓝牙栈优化了发送队列逻辑,你可以直接批量调用notifyCharacteristicChanged,底层会自动排队发送,不需要上层等待回调,性能接近iOS批量发送的体验。

内容的提问来源于stack exchange,提问作者Muneer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 10:57:01