React Native BLE Manager:OTA升级写入回调追踪问题
React Native Ble Manager OTA升级:追踪单条写入回调与进度计算
方案一:修改iOS原生代码搭建桥接回调
既然你已经在iOS ObjC代码中观察到每次写入都会触发回调,可直接在原生层添加事件通知,将写入结果传递到JavaScript层:
1. 修改iOS原生代码(react-native-ble-manager)
找到BleManager.m中的peripheral:didWriteValueForCharacteristic:error:方法,在原有日志代码后添加事件发送逻辑:
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { // 保留原有日志 NSLog(@"Write completed for characteristic %@", characteristic.UUID); // 组装事件数据,传递外设ID、特征UUID、错误信息和写入字节数 NSDictionary *eventData = @{ @"peripheralId": peripheral.identifier.UUIDString, @"characteristicUUID": characteristic.UUID.UUIDString, @"error": error ? error.localizedDescription : [NSNull null], @"bytesWritten": @(characteristic.value.length) }; // 发送事件到JS层 [self sendEventWithName:@"BleManagerWriteCompleted" body:eventData]; }
注:react-native-ble-manager的核心类默认已实现事件发射器能力,无需额外调整继承关系。
2. JavaScript层监听事件
在RN代码中通过NativeEventEmitter监听原生发送的写入完成事件,实时更新进度:
import { NativeEventEmitter, Platform, useEffect, useState } from 'react-native'; import BleManager from 'react-native-ble-manager'; const BleManagerEmitter = new NativeEventEmitter(BleManager); // 进度状态管理 const [otaProgress, setOtaProgress] = useState(0); let totalOtaBytes = 0; let sentBytes = 0; // 初始化OTA总字节数(从固件数据中获取) const initOTA = (firmwareData) => { totalOtaBytes = firmwareData.length; sentBytes = 0; setOtaProgress(0); }; // 更新进度逻辑 const updateWriteProgress = (bytes) => { sentBytes += bytes; const progress = Math.min((sentBytes / totalOtaBytes) * 100, 100); setOtaProgress(progress.toFixed(2)); }; // 监听iOS写入完成事件 useEffect(() => { let writeSubscription; if (Platform.OS === 'ios') { writeSubscription = BleManagerEmitter.addListener( 'BleManagerWriteCompleted', (event) => { // 过滤当前OTA操作的外设和特征(避免其他BLE写入干扰) if (event.peripheralId === yourPeripheralId && event.characteristicUUID === yourOtaCharUUID) { updateWriteProgress(event.bytesWritten); } } ); } // 组件卸载时取消订阅 return () => writeSubscription?.remove(); }, []);
3. 保留修改的技巧
直接修改node_modules代码会在依赖更新后丢失,推荐用patch-package保存补丁:
- 修改完原生代码后,运行
npx patch-package react-native-ble-manager - 项目根目录生成
patches文件夹,将补丁文件提交到代码仓库 - 其他开发者安装依赖后,执行
npx patch-package即可自动应用修改
方案二:JS层手动分块发送(无需修改原生)
如果不想改动原生库,可将OTA数据按MTU大小拆分,逐块调用BleManager.write,每块写入完成后更新进度:
const sendOTAData = async (peripheralId, charUUID, firmwareData, mtuSize) => { // MTU减去BLE协议头,得到实际可写入的字节数 const chunkSize = mtuSize - 3; const totalChunks = Math.ceil(firmwareData.length / chunkSize); let currentChunk = 0; for (let i = 0; i < firmwareData.length; i += chunkSize) { const chunk = firmwareData.slice(i, i + chunkSize); // 等待当前块写入完成再发送下一块 await BleManager.write(peripheralId, charUUID, chunk); currentChunk++; const progress = (currentChunk / totalChunks) * 100; setOtaProgress(progress.toFixed(2)); } };
注意:这种方式依赖
BleManager.write的Promise是否会在单块写入完成后才resolve,如果库内部做了批量写入优化,该方法可能无法准确追踪单条写入。
内容的提问来源于stack exchange,提问作者MertCelik
相关产品推荐
相关产品推荐

