如何使用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(); } }
注意事项
- 权限检查:确保已经申请了BLE相关权限,Android 6.0+需要
ACCESS_FINE_LOCATION,Android 12+需要BLUETOOTH_SCAN和BLUETOOTH_CONNECT权限,并且在运行时请求。 - 错误容错:如果某个特征不支持通知,订阅会抛出错误,可以用
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(); // 跳过错误,返回空流 }); - 自动重连:如果需要设备断开后自动重连,把
establishConnection(false)改为establishConnection(true),或者用retryWhen实现自定义重连策略(比如间隔重试)。
内容的提问来源于stack exchange,提问作者user3828374
相关产品推荐
相关产品推荐

