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

如何使用RxAndroidBle 1.8.1从多个服务读取通知?

实现多BLE服务特征通知订阅的思路(RxAndroidBle 1.8.1 + RxJava 1.4.0)

我之前在项目里用RxAndroidBle 1.x版本处理过多服务的通知订阅,刚好和你的版本匹配,给你梳理一套一步步的实现思路,应该能解决你的问题。

核心思路概述

RxAndroidBle的设计是基于RxJava的流操作,所以我们可以把连接建立、多特征通知订阅、数据流合并这几个步骤通过RxJava的操作符串联起来,最终统一处理不同服务的通知数据。


步骤1:初始化BLE连接

首先要通过RxBleClient获取目标设备,然后建立BLE连接。这里要注意连接的配置(比如是否自动重连),以及订阅连接的生命周期,避免内存泄漏。

// 初始化RxBleClient
RxBleClient rxBleClient = RxBleClient.create(getApplicationContext());
// 通过MAC地址获取目标设备
RxBleDevice targetDevice = rxBleClient.getBleDevice("你的设备MAC地址");

步骤2:定义服务与特征的UUID

先把需要订阅的三个服务对应的特征UUID定义好,这是BLE通信的关键标识:

// 温度服务与特征UUID(标准UUID)
private static final UUID TEMPERATURE_SERVICE_UUID = UUID.fromString("00001809-0000-1000-8000-00805f9b34fb");
private static final UUID TEMPERATURE_CHAR_UUID = UUID.fromString("00002a1c-0000-1000-8000-00805f9b34fb");

// 电池服务与特征UUID(标准UUID)
private static final UUID BATTERY_SERVICE_UUID = UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb");
private static final UUID BATTERY_CHAR_UUID = UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb");

// 自定义服务与特征UUID(替换成你的实际UUID)
private static final UUID CUSTOM_SERVICE_UUID = UUID.fromString("你的自定义服务UUID");
private static final UUID CUSTOM_CHAR_UUID = UUID.fromString("你的自定义特征UUID");

步骤3:连接+多特征通知订阅合并

这是核心部分:建立连接后,分别订阅每个特征的通知,然后用RxJava的merge操作符把多个通知流合并成一个,最后统一处理不同来源的数据。

3.1 辅助类:区分通知来源

为了能在合并后的流里区分是哪个特征的通知,我们可以定义一个简单的包装类:

// 枚举标识通知类型
enum NotificationType {
    TEMPERATURE, BATTERY, CUSTOM
}

// 包装通知数据与类型
class BleNotification {
    private NotificationType type;
    private byte[] rawData;

    public BleNotification(NotificationType type, byte[] rawData) {
        this.type = type;
        this.rawData = rawData;
    }

    public NotificationType getType() { return type; }
    public byte[] getRawData() { return rawData; }
}

3.2 核心代码实现

// 保存订阅的Disposable,用于生命周期管理
private Disposable bleConnectionDisposable;

// 启动连接与通知订阅
private void startBleNotificationSubscription() {
    bleConnectionDisposable = targetDevice.establishConnection(false) // false=不自动重连,按需改为true
            .flatMap(rxBleConnection -> {
                // 订阅温度特征通知
                Observable<BleNotification> temperatureStream = rxBleConnection.setupNotification(TEMPERATURE_CHAR_UUID)
                        .flatMap(notificationObservable -> notificationObservable) // 展开通知流
                        .map(rawData -> new BleNotification(NotificationType.TEMPERATURE, rawData));

                // 订阅电池特征通知
                Observable<BleNotification> batteryStream = rxBleConnection.setupNotification(BATTERY_CHAR_UUID)
                        .flatMap(notificationObservable -> notificationObservable)
                        .map(rawData -> new BleNotification(NotificationType.BATTERY, rawData));

                // 订阅自定义特征通知
                Observable<BleNotification> customStream = rxBleConnection.setupNotification(CUSTOM_CHAR_UUID)
                        .flatMap(notificationObservable -> notificationObservable)
                        .map(rawData -> new BleNotification(NotificationType.CUSTOM, rawData));

                // 合并三个通知流,任意一个流有数据都会触发回调
                return Observable.merge(temperatureStream, batteryStream, customStream);
            })
            .subscribeOn(Schedulers.io()) // 耗时操作在IO线程
            .observeOn(AndroidSchedulers.mainThread()) // 回调到主线程处理UI
            .subscribe(
                    bleNotification -> {
                        // 根据通知类型处理数据
                        switch (bleNotification.getType()) {
                            case TEMPERATURE:
                                parseAndShowTemperature(bleNotification.getRawData());
                                break;
                            case BATTERY:
                                parseAndShowBattery(bleNotification.getRawData());
                                break;
                            case CUSTOM:
                                parseAndHandleCustomData(bleNotification.getRawData());
                                break;
                        }
                    },
                    throwable -> {
                        // 处理错误:连接断开、订阅失败等
                        Log.e("BLE", "Notification error occurred: ", throwable);
                        // 可选:在这里实现重连逻辑
                    },
                    () -> {
                        // 流完成:一般是连接正常断开时触发
                        Log.d("BLE", "BLE connection closed");
                    }
            );
}

// 示例:解析温度数据(根据你的设备协议调整)
private void parseAndShowTemperature(byte[] rawData) {
    // 假设温度数据是小端格式的float,转换逻辑示例
    float temperature = ByteBuffer.wrap(rawData).order(ByteOrder.LITTLE_ENDIAN).getFloat();
    textViewTemperature.setText(String.format("温度: %.1f°C", temperature));
}

// 示例:解析电池数据
private void parseAndShowBattery(byte[] rawData) {
    int batteryLevel = rawData[0] & 0xFF; // 标准电池特征是单字节百分比
    textViewBattery.setText(String.format("电量: %d%%", batteryLevel));
}

// 自定义数据解析(根据你的设备协议实现)
private void parseAndHandleCustomData(byte[] rawData) {
    // 你的自定义数据处理逻辑
}

步骤4:生命周期管理(关键!避免内存泄漏)

在Activity/Fragment的销毁方法中,一定要取消订阅,释放资源:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (bleConnectionDisposable != null && !bleConnectionDisposable.isDisposed()) {
        bleConnectionDisposable.dispose();
    }
}

注意事项

  1. 权限检查:确保已经申请了BLE相关权限,Android 6.0+需要ACCESS_FINE_LOCATION,Android 12+需要BLUETOOTH_SCAN和BLUETOOTH_CONNECT权限,并且在运行时请求。
  2. 错误容错:如果某个特征不支持通知,订阅会抛出错误,可以用onErrorResumeNext操作符跳过单个特征的错误,不影响其他特征的订阅,比如:
    Observable<BleNotification> temperatureStream = rxBleConnection.setupNotification(TEMPERATURE_CHAR_UUID)
            .flatMap(notificationObservable -> notificationObservable)
            .map(rawData -> new BleNotification(NotificationType.TEMPERATURE, rawData))
            .onErrorResumeNext(throwable -> {
                Log.w("BLE", "Temperature notification subscribe failed", throwable);
                return Observable.empty(); // 跳过错误,返回空流
            });
    
  3. 自动重连:如果需要设备断开后自动重连,把establishConnection(false)改为establishConnection(true),或者用retryWhen实现自定义重连策略(比如间隔重试)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:18:03