OTA固件升级
OTA固件升级(Over-The-Air Firmware Upgrade)是 Android-JL_Bluetooth 应用中负责向杰理(Jieli)蓝牙设备推送固件、完成空中升级的完整能力,涵盖固件版本查询、OTA 服务检测、固件文件下载、蓝牙连接切换、升级传输与进度上报的全流程。
Purpose and Scope
本页介绍 btsmart 模块中 OTA 固件升级能力的端到端实现,包括:
- 升级链路的分层架构:UI 层(
FirmwareOtaFragment)→ 业务层(OtaPresenterImpl)→ 桥接层(OTAManager)→ OTA SDK(jl_bt_otaAAR)与 RCSP 通信栈。 - 核心接口契约
IOtaContract(Presenter / View 双向回调)。 - 固件文件的选择策略(
.bfu/.ufw)、OTA 传输配置(SPP 优先、MTU、回连记录)与设备版本判断逻辑。 - 数据模型
FirmwareOtaItem/OtaStageInfo与列表适配器FirmwareOtaAdapter的展示组织方式。
以下内容属于其他页面主题,本页不展开:蓝牙扫描/连接管理(RCSP 通信栈)、音乐播放控制(PlayControlImpl)、HTTP 平台接口协议(jl_http)。本页仅在 OTA 流程依赖它们时说明交互关系。
Overview
OTA 固件升级是杰理蓝牙 SDK 生态中设备维护的关键环节。Android 端通过 jl_bt_ota 库(仓库中以 jl_bt_ota_V1.10.0_10932-release.aar 形式集成)完成固件数据传输,但该库需要上层应用提供蓝牙连接、数据收发与设备信息等基础设施。OTAManager 正是这一"适配层":它继承 BluetoothOTAManager,将应用的 RCSP 通信栈(RCSPController)桥接到 OTA 库期望的抽象接口上。
典型使用场景:
- 检测新固件:用户进入固件升级页面,App 通过
JL_HttpClient请求 OTA 服务,获取服务器端固件版本信息(OtaMessage)。 - 判断是否需要升级:将设备当前固件版本号与服务器版本比较。
- 下载固件:通过 HTTP 下载固件文件(.bfu/.ufw)到本地。
- 执行升级:选择固件文件路径,
OTAManager处理设备重连、地址映射、MTU 协商,由 OTA SDK 完成固件分包传输,UI 实时显示进度与阶段信息。
整个流程的关键设计意图是解耦:UI 与业务逻辑只依赖 IOtaContract 接口;OtaPresenterImpl 聚合 OTAManager 与 JL_HttpClient;OTAManager 屏蔽 OTA 库对底层蓝牙的复杂要求,同时利用 DeviceAddrManager 保存设备地址映射,保证 OTA 前后设备回连的连续性。
Architecture
OTA 固件升级整体采用 MVP(Model-View-Presenter)分层,配合"桥接适配"模式将 OTA SDK 与 RCSP 通信栈对接:
flowchart TD
subgraph sg_UI["UI Layer (ui/ota)"]
Fragment["FirmwareOtaFragment<br/>(IOtaView)"]
Adapter["FirmwareOtaAdapter"]
Item["FirmwareOtaItem / OtaStageInfo"]
end
subgraph sg_Presenter["Presenter Layer"]
Contract["IOtaContract"]
Presenter["OtaPresenterImpl<br/>(IOtaPresenter)"]
end
subgraph sg_Bridge["OTA Bridge (tool/upgrade)"]
OTAManager["OTAManager<br/>extends BluetoothOTAManager"]
Reconnect["ReconnectAddress"]
end
subgraph sg_SDK["SDK Layer"]
OtaLib["jl_bt_ota AAR<br/>BluetoothOTAManager"]
RCSP["RCSPController<br/>(RCSP通信栈)"]
Http["JL_HttpClient<br/>(jl_http)"]
AddrMgr["DeviceAddrManager"]
end
Fragment -->|"implements"| Contract
Adapter --> Item
Fragment --> Presenter
Presenter -->|"implements"| Contract
Presenter --> OTAManager
Presenter --> Http
OTAManager --> OtaLib
OTAManager --> RCSP
OTAManager --> AddrMgr
OtaLib -->|"sendData/connect 回调"| OTAManager
RCSP -->|"BLE设备"| Device["蓝牙设备"]
Http -->|"OtaMessage / 文件下载"| Server["OTA 服务器"]
架构分层说明:
- UI 层:
FirmwareOtaFragment实现IOtaView,通过FirmwareOtaAdapter展示升级阶段列表;FirmwareOtaItem作为多布局列表条目承载阶段信息。 - Presenter 层:
OtaPresenterImpl实现IOtaPresenter,串联"查版本 → 判断 → 下载 → 升级"的业务编排,并将 OTA 库回调转发为IOtaView的视图事件。 - 桥接层:
OTAManager是核心适配器,把 RCSP 的蓝牙连接、GATT、数据收发能力注入BluetoothOTAManager,并管理 OTA 前后的设备地址记录(ReconnectAddress)。 - SDK 层:
jl_bt_ota提供升级协议实现;RCSPController提供实际 BLE 连接;JL_HttpClient提供 OTA 服务查询与文件下载;DeviceAddrManager持久化设备地址映射,保证升级后回连。
注:
OTAManager的构造函数中若 RCSP 已连接设备,会立即同步目标设备、触发onBtDeviceConnection并同步 MTU(mtu + 3),确保进入升级页面前 OTA 库即处于就绪状态。
主要实现组件
OTAManager —— OTA 桥接核心
OTAManager 位于 com.jieli.btsmart.tool.upgrade,继承自 com.jieli.jl_bt_ota.impl.BluetoothOTAManager。它是整个升级能力的"接线层",负责把应用侧蓝牙能力提供给 OTA 库:
| 职责 | 实现方式 |
|---|---|
| 连接管理 | 覆写 connectBluetoothDevice / disconnectBluetoothDevice,委托给 RCSPController |
| 数据通道 | 覆写 sendDataToDevice,委托给 RCSP;onBleDataNotification 回调中转发给 onReceiveDeviceData |
| 设备状态 | 通过 BluetoothCallbackImpl 监听 RCSP 连接事件,驱动 OTA 库的 onBtDeviceConnection 与 MTU 同步 |
| 升级编排 | 覆写 startOTA,包装 IUpgradeCallback,处理"需要重连"时的地址记录与还原 |
| 固件判断 | judgeDeviceNeedToOta 比较设备版本与服务器版本 |
构造函数中的关键动作(OTAManager.java#L47-L60):
- 向
RCSPController注册蓝牙回调mBluetoothCallback; - 调用
configureOTA()完成 OTA 传输配置; - 若设备已连接,则设置目标设备、通知 OTA 库连接成功,并在 BLE 连接下同步 MTU。
版本判断逻辑(OTAManager.java#L150-L161):通过 RCSPController.getDeviceInfo(device) 获取 TargetInfoResponse 得到设备版本码 versionCode,用 ParseHelper.convertVersionByString 解析服务器版本;当 versionCode < serverFirmware 或 serverFirmware == 0(服务器未给出有效版本,视为强制升级)时返回 true。
固件路径选择(OTAManager.java#L163-L192):依据设备 sdkType 与 JLChipFlag.JL_CHIP_FLAG_693X_TWS_HEADSET 比较,老平台优先查找 .bfu 文件(回退到常量 FIRMWARE_UPGRADE_FILE),新平台(AC693 及以上)查找 .ufw 文件(回退到 FIRMWARE_UPGRADE_FILE_AC693)。
业务编排层:OtaPresenterImpl
OtaPresenterImpl 实现 IOtaContract.IOtaPresenter,继承 BluetoothBasePresenter,并实现 DevicePopDialogFilter.IgnoreFilter 用于在升级期间屏蔽设备弹窗干扰。它聚合了三个关键依赖(OtaPresenterImpl.java#L56-L66):
OTAManager mOTAManager:升级执行器;JL_HttpClient:OTA 服务查询与文件下载;Handler mHandler(主线程 Looper):用于 UI 线程调度。
业务方法映射:
| 接口方法 | 内部动作 | 视图回调 |
|---|---|---|
checkFirmwareOtaService(authKey, projectCode[, md5]) | 调 JL_HttpClient.requestOTAFileByV2(带 md5 的 V2 接口)或 requestOTAFile | onOtaMessageChange / onGetOtaMessageError |
judgeDeviceNeedToOta(device, message) | 委托 OTAManager.judgeDeviceNeedToOta | — |
downloadFile(url, saveFilePath) | 调 JL_HttpClient.downloadFile | onDownloadStart/Progress/Stop/Error |
startFirmwareOta(filePath) | 校验文件存在 → 设置固件路径 → OTAManager.startOTA | onOtaStart / onOtaProgress / onOtaError |
cancelFirmwareOta() | OTAManager.cancelOTA() | onOtaCancel |
disconnectDevice() | 加入忽略列表后由 RCSP 断开 | — |
destroy() | 复位状态、销毁 RCSP 与 OTAManager、清空 Handler | — |
升级前的业务处理(mIUpgradeCallback.onStartOTA,OtaPresenterImpl.java#L229-L240):
- 标记
MainApplication.setOTA(true),全局标识进入升级态; - 记录当前设备
sdkType; - 若音乐正在播放,调用
PlayControlImpl.pause()暂停,避免音频流干扰升级通道; - 调用
changeDeviceStatus()处理单备份(single backup)设备的 OTA 通道地址记录; - 通知视图
onOtaStart()。
单备份设备通道处理(changeDeviceStatus,OtaPresenterImpl.java#L165-L189):对于不支持双备份的设备,根据 deviceInfo.getSingleBackupOtaWay() 判断 OTA 通道:若当前为 BLE 连接且 OTA 走 SPP,则把设备的 EDR 地址写入 DeviceAddrManager 历史记录;反之若走 BLE 通道,则写入 BLE 地址。这一机制保证升级过程中切换传输通道后,App 仍能定位到原设备。
Core Flow —— 完整升级流程
sequenceDiagram
participant U as User/Fragment
participant P as OtaPresenterImpl
participant H as JL_HttpClient
participant M as OTAManager
participant O as jl_bt_ota SDK
participant R as RCSPController
participant D as 蓝牙设备
U->>P: checkFirmwareOtaService(authKey, projectCode)
P->>H: requestOTAFile / requestOTAFileByV2
H-->>P: OtaMessage(version, url, md5...)
P-->>U: onOtaMessageChange(message)
U->>P: judgeDeviceNeedToOta(device, message)
P->>M: judgeDeviceNeedToOta
M-->>P: true (版本落后)
U->>P: downloadFile(url, saveFilePath)
P->>H: downloadFile
H-->>P: onStop(outputPath)
P-->>U: onDownloadStop(path)
U->>P: startFirmwareOta(filePath)
P->>M: startOTA(callback)
M->>O: 启动升级(配置: SPP优先/BLE_MTU_MIN)
O->>R: connectBluetoothDevice / sendDataToDevice
R->>D: BLE 连接与数据收发
D-->>R: 升级应答/进度
R-->>O: onBtDeviceConnection / onReceiveDeviceData
O-->>M: onProgress(type, progress) / onNeedReconnect
M-->>P: 回调转发(onNeedReconnect 时记录/还原地址)
P-->>U: onOtaProgress / onOtaStop / onOtaError
步骤拆解:
- 查询 OTA 服务:Presenter 携带
authKey、projectCode(可选md5)请求服务器,得到OtaMessage(含服务器固件版本、下载地址等),成功后回调onOtaMessageChange。 - 版本比较:
OTAManager.judgeDeviceNeedToOta用设备版本码与服务器版本比较,决定是否展示"有新固件"。 - 下载固件:
downloadFile通过 HTTP 下载到saveFilePath,onDownloadStop时把下载路径设为upgradeFilePath。 - 执行升级:
startFirmwareOta校验文件存在后调用OTAManager.startOTA,OTA SDK 按配置(SPP 优先、最小 MTU、不使用应用层重连)驱动 RCSP 与设备通信。 - 传输与回调:升级过程中 SDK 上报进度与阶段,
OTAManager包装的IUpgradeCallback负责onNeedReconnect时的地址记录(ReconnectAddress)与onStopOTA时的历史地址还原(OTAManager.java#L100-L141)。
数据模型与展示
- FirmwareOtaItem(FirmwareOtaItem.java#L13-L74)实现
MultiItemEntity,是升级进度列表的条目模型:itemType区分两种布局(LAYOUT_ONE = 0/LAYOUT_TWO = 1),content/value承载文本(如"当前版本"、"升级到 XX"),otaStageInfo携带阶段信息,isShowIcon控制图标显示。 - OtaStageInfo:位于
data/model/ota包下,与FirmwareOtaItem配套,描述升级阶段(如擦除、传输、校验、重启等)的状态数据,由FirmwareOtaAdapter渲染。 - FirmwareOtaAdapter:
data/adapter下的 RecyclerView 适配器,按itemType加载不同布局展示升级进度列表。
classDiagram
class IOtaContract {
<<interface>>
}
class IOtaPresenter {
<<interface>>
+getOtaMessage() OtaMessage
+checkFirmwareOtaService(authKey, projectCode, md5) void
+judgeDeviceNeedToOta(device, message) boolean
+downloadFile(url, saveFilePath) void
+startFirmwareOta(filePath) void
+cancelFirmwareOta() void
+destroy() void
}
class IOtaView {
<<interface>>
+onOtaMessageChange(message) void
+onDownloadProgress(progress) void
+onOtaProgress(type, progress) void
+onOtaError(code, message) void
}
class OtaPresenterImpl {
-mOTAManager OTAManager
-mOtaMessage OtaMessage
-mUpgradeState int
+startFirmwareOta(filePath) void
}
class OTAManager {
-mTargetDevice BluetoothDevice
-mReconnectAddress ReconnectAddress
+startOTA(callback) void
+judgeDeviceNeedToOta(device, message) boolean
-configureOTA() void
}
class FirmwareOtaItem {
-itemType int
-content String
-value String
-otaStageInfo OtaStageInfo
-isShowIcon boolean
}
IOtaContract <|-- IOtaPresenter
IOtaContract <|-- IOtaView
IOtaPresenter <|.. OtaPresenterImpl
OtaPresenterImpl --> OTAManager
OtaPresenterImpl ..> IOtaView : 回调
OTAManager --> FirmwareOtaItem : 无直接依赖(经Presenter)
FirmwareOtaItem --> OtaStageInfo
Usage Examples
示例 1:创建 OTAManager 并完成 OTA 初始化
以下代码展示了 OTAManager 的构造与就绪逻辑:注册 RCSP 蓝牙回调、执行 OTA 配置,并在设备已连接时同步目标设备与 MTU。
public OTAManager(Context context) {
super(context);
mRCSPController.getBtOperation().registerBluetoothCallback(mBluetoothCallback);
configureOTA();
if (mRCSPController.isDeviceConnected()) {
BluetoothDevice device = mRCSPController.getUsingDevice();
setTargetDevice(device);
onBtDeviceConnection(device, StateCode.CONNECTION_OK);
if (mRCSPController.getBtOperation().isConnectedBLEDevice(device)) {
onMtuChanged(mRCSPController.getBtOperation().getDeviceGatt(device),
mRCSPController.getBtOperation().getBleMtu(device), BluetoothGatt.GATT_SUCCESS);
}
}
}
Source: OTAManager.java#L47-L60
设计意图:升级页面打开时设备通常已经连接,构造函数主动把现有连接"移交"给 OTA 库,避免二次扫描连接;onMtuChanged 传入 GATT_SUCCESS 让 OTA 库立即按当前 MTU 初始化传输分包。
示例 2:OTA 传输配置(configureOTA)
private void configureOTA() {
BluetoothOTAConfigure configure = BluetoothOTAConfigure.createDefault();
configure.setPriority(BluetoothOTAConfigure.PREFER_SPP)
.setMtu(BluetoothConstant.BLE_MTU_MIN)
.setUseReconnect(false)
.setUseAuthDevice(false)
.setBleScanMode(2);//设置高性能搜索模式
String upgradeFilePath = FileUtil.createFilePath(MainApplication.getApplication(), MainApplication.getApplication().getPackageName(), SConstant.DIR_UPDATE);
DeviceInfo deviceInfo = mRCSPController.getDeviceInfo();
String filePath;
if (deviceInfo != null && deviceInfo.getSdkType() < JLChipFlag.JL_CHIP_FLAG_693X_TWS_HEADSET) {
filePath = AppUtil.obtainUpdateFilePath(upgradeFilePath, ".bfu");
if (filePath == null) {
upgradeFilePath += "/" + SConstant.FIRMWARE_UPGRADE_FILE;
} else {
upgradeFilePath = filePath;
}
} else {
filePath = AppUtil.obtainUpdateFilePath(upgradeFilePath, ".ufw");
if (filePath == null) {
upgradeFilePath += "/" + SConstant.FIRMWARE_UPGRADE_FILE_AC693;
} else {
upgradeFilePath = filePath;
}
}
configure.setFirmwareFilePath(upgradeFilePath);
configure(configure);
}
Source: OTAManager.java#L163-L192
要点:老平台(sdkType 低于 693X TWS)优先 .bfu 文件、新平台用 .ufw 文件;若目录下找不到对应扩展名文件,则回退到 SConstant 中定义的固定文件名。PREFER_SPP 表示固件传输优先走 SPP 通道(经典蓝牙),MTU 取 BLE 最小值以兼容低端设备。
示例 3:Presenter 编排"查询 → 判断 → 下载 → 升级"
@Override
public void checkFirmwareOtaService(String authKey, String projectCode, String md5) {
JL_Log.i(TAG, "checkFirmwareOtaService >> authKey : " + authKey + ", projectCode : " + projectCode + ", md5 : " + md5);
if (!TextUtils.isEmpty(md5)) {
JL_HttpClient.getInstance().requestOTAFileByV2(authKey, projectCode, Constant.PLATFORM_FIRMWARE, md5, mOtaMessageListener);
} else {
JL_HttpClient.getInstance().requestOTAFile(authKey, projectCode, Constant.PLATFORM_FIRMWARE, mOtaMessageListener);
}
}
@Override
public void startFirmwareOta(String filePath) {
if (filePath == null || !FileUtil.checkFileExist(filePath)) {
mView.onOtaError(ErrorCode.SUB_ERR_FILE_NOT_FOUND, AppUtil.getContext().getString(R.string.ota_error_msg_file_not_exist));
return;
}
upgradeFilePath = filePath;
JL_Log.i(TAG, "startFirmwareOta >> " + filePath);
mOTAManager.getBluetoothOption().setFirmwareFilePath(filePath);
mOTAManager.startOTA(mIUpgradeCallback);
}
Sources:
startFirmwareOta 是升级的"守门"方法:先校验固件文件是否存在,否则以 SUB_ERR_FILE_NOT_FOUND 错误码通知视图;通过后再把文件路径注入 OTA 库的 BluetoothOption 并启动升级。
Configuration Options
OTA 传输行为由 BluetoothOTAConfigure 控制,配置集中在 OTAManager.configureOTA():
| 配置项 | 类型 | 默认值/设定值 | 说明 |
|---|---|---|---|
setPriority | int | BluetoothOTAConfigure.PREFER_SPP | 固件传输通道优先级,SPP(经典蓝牙)优先 |
setMtu | int | BluetoothConstant.BLE_MTU_MIN | BLE MTU 取最小值,保证低端设备兼容 |
setUseReconnect | boolean | false | 不使用 OTA 库内置自动回连,由上层 ReconnectAddress 管理 |
setUseAuthDevice | boolean | false | 不要求设备鉴权 |
setBleScanMode | int | 2 | BLE 扫描模式,2 表示高性能搜索 |
setFirmwareFilePath | String | 按平台选择 .bfu/.ufw | 固件文件路径(老平台 .bfu,693X+ 平台 .ufw) |
API Reference
OTAManager(继承 BluetoothOTAManager)
BluetoothDevice getConnectedDevice()
- 返回当前目标升级设备
mTargetDevice。 - Source: OTAManager.java#L63-L65
void connectBluetoothDevice(BluetoothDevice device)
- 升级前连接设备;若
ReconnectAddress需要记录 OTA 地址,则保存并更新历史 OTA 地址,随后通过 RCSP 以 BLE 协议连接。 - Source: OTAManager.java#L73-L80
boolean sendDataToDevice(BluetoothDevice device, byte[] data)
- 向设备发送 OTA 数据包,委托
RCSPController.sendDataToDevice。
void startOTA(IUpgradeCallback callback)
- 启动升级;包装回调以处理
onNeedReconnect(记录源/映射地址)、onStopOTA(还原历史地址记录)、onCancelOTA(复位)。 - Throws/Errors:通过
onError(BaseError)上报(如设备未连接SUB_ERR_REMOTE_NOT_CONNECTED)。 - Source: OTAManager.java#L100-L141
boolean judgeDeviceNeedToOta(BluetoothDevice device, OtaMessage message)
- 参数:
device目标设备、message服务器 OTA 消息。 - 返回:设备版本低于服务器版本,或服务器版本为 0(视为强制)时返回
true。 - 注意:
device未连接(TargetInfoResponse为 null)时回调SUB_ERR_REMOTE_NOT_CONNECTED并返回false。 - Source: OTAManager.java#L150-L161
IOtaContract.IOtaPresenter
| 方法 | 参数 | 说明 |
|---|---|---|
checkFirmwareOtaService | String authKey, String projectCode[, String md5] | 查询服务器固件信息;带 md5 走 V2 接口 |
judgeDeviceNeedToOta | BluetoothDevice, OtaMessage | 判断设备是否需要升级 |
downloadFile | String url, String saveFilePath | 下载固件文件到本地 |
isFirmwareOta | — | 是否正在 OTA(委托 mOTAManager.isOTA()) |
startFirmwareOta | String filePath | 开始升级(文件不存在则报 SUB_ERR_FILE_NOT_FOUND) |
cancelFirmwareOta | — | 取消升级 |
disconnectDevice | — | 断开设备并加入弹窗忽略列表 |
setUpgradeState | int state | 记录升级状态 |
destroy | — | 释放资源、复位全局状态 |
IOtaContract.IOtaView(视图回调)
onOtaMessageChange(OtaMessage):服务器 OTA 信息就绪;onGetOtaMessageError(int code, String message):查询失败;onDownloadStart/Progress/Stop/Error:下载生命周期;onOtaStart/Progress(int type, float progress)/Stop/Cancel/Error:升级生命周期,type区分阶段、progress为 0~1 浮点进度。
Source: IOtaContract.java#L14-L68
Failure Modes、边界情况与并发
典型失败模式
| 失败场景 | 处理方式 | 源码依据 |
|---|---|---|
| 设备未连接即调用版本判断 | getDeviceInfo 返回 null,回调 SUB_ERR_REMOTE_NOT_CONNECTED 并返回 false | OTAManager.java#L150-L161 |
| 固件文件不存在/路径为空 | startFirmwareOta 直接回调 onOtaError(SUB_ERR_FILE_NOT_FOUND, ...),不进入升级 | OtaPresenterImpl.java#L118-L128 |
| OTA 服务查询失败(网络/鉴权) | mOtaMessageListener.onError 转发 onGetOtaMessageError(code, message) | OtaPresenterImpl.java#L191-L204 |
| 固件下载失败/中断 | mDownloadListener.onError 转发 onDownloadError,UI 提示后终止流程 | OtaPresenterImpl.java#L206-L227 |
| 升级过程中设备断开/连接失败 | mBluetoothCallback.onConnection 中 CONNECTION_FAILED/CONNECTION_DISCONNECT 时清空目标设备,交由 OTA 库错误回调 | OTAManager.java#L201-L226 |
边界情况与重连地址管理
- OTA 前后设备地址变化:部分设备升级时会切换蓝牙地址(如从 BLE 切 SPP 或地址重映射)。
ReconnectAddress在onNeedReconnect时记录源地址与映射地址并写入DeviceAddrManager.updateHistoryOtaAddress;onStopOTA时还原putDeviceAddr并清空历史 OTA 地址(OTAManager.java#L109-L128)。connectBluetoothDevice中仅当isNeedRecordOtaAddress为 true 才记录,避免普通重连污染历史。 - 服务器版本为 0:
judgeDeviceNeedToOta中serverFirmware == 0视为需要升级(服务器未下发有效版本时保守处理)。 - MTU 协商:回调中 MTU 均加 3(
mtu + 3、block + 3),覆盖 BLE 协议 ATT 头部开销,确保实际数据负载与 MTU 一致(OTAManager.java#L210-L231)。 - 双备份 vs 单备份:
changeDeviceStatus只对不支持双备份(isSupportDoubleBackup() == false)的设备做通道地址迁移;双备份设备直接复用现有连接,减少中断。
并发与线程
- 所有视图回调经由
OtaPresenterImpl构造时创建的Handler(Looper.getMainLooper())与主线程衔接;destroy()中removeCallbacksAndMessages(null)清空挂起任务,防止页面销毁后回调泄漏。 OTAManager构造时注册的mBluetoothCallback在release()中显式反注册(OTAManager.java#L144-L148),与OtaPresenterImpl.destroy()的destroyOTAManager()配合,保证页面生命周期内不会出现重复回调。- 全局状态:
MainApplication.setOTA(true/false)与setNeedBanDialog(true/false)在start()/destroy()中成对设置,用于升级期间抑制系统弹窗(如断开重连提示),避免用户误操作打断升级。
性能与运维注意
- 传输通道:
PREFER_SPP优先使用经典蓝牙 SPP 传输固件,吞吐高于 BLE,缩短升级耗时;BLE 作为降级通道,MTU 取最小值以最大化兼容性。 - 扫描模式:
setBleScanMode(2)使用高性能搜索模式,减少 OTA 阶段设备丢失概率,代价是功耗略高——升级场景属短时高优先级操作,可接受。 - 下载:固件文件下载走
JL_HttpClient独立监听器,进度以浮点百分比上报,UI 可展示进度条;升级前建议提示用户保持 App 前台与蓝牙开启。 - 日志:关键路径均打点
JL_Log(如judgeDeviceNeedToOta打印本地/服务器版本、onBleDataNotification打印原始数据),便于线上定位升级失败问题。 - 升级状态隔离:
isFirmwareOta()暴露OTAManager.isOTA()供外部查询,业务层通过mUpgradeState记录阶段,避免下载/升级并发冲突。
Extension Points
- 自定义固件判断策略:
judgeDeviceNeedToOta是独立的可覆写方法,可扩展为"版本区间/白名单/灰度"等策略。 - OTA 传输配置:
configureOTA()集中了BluetoothOTAConfigure的全部参数,如需开启鉴权设备(setUseAuthDevice(true))、调整 MTU 或启用库内回连,只需修改此处。 - 固件文件命名:固件文件查找扩展名(
.bfu/.ufw)与回退常量(SConstant.FIRMWARE_UPGRADE_FILE/FIRMWARE_UPGRADE_FILE_AC693)定义在常量层,新增固件格式只需扩展该处。 - 视图扩展:
IOtaContract.IOtaView定义了完整回调集合,新 UI(如桌面小组件、通知栏进度)可实现该接口复用同一 Presenter。
Tests
仓库中未发现针对 OTA 模块的独立单元测试源码;该能力的正确性主要依赖 jl_bt_ota SDK 的协议实现与真机联调(升级为硬件强相关流程)。可验证的场景包括:版本判断矩阵(旧版本/同版本/服务器版本为 0)、固件文件缺失路径、下载中断恢复、升级中断开重连后的地址还原。
Related Links
- FirmwareOtaFragment.java —— 升级页视图(
IOtaView实现) - FirmwareOtaAdapter.java —— 升级进度列表适配器
- OtaStageInfo.java —— 升级阶段数据模型
- jl_bt_ota AAR ——
BluetoothOTAManager/BluetoothOTAConfigure/IUpgradeCallback所在 SDK - UploadDeviceInfoTask.java —— RCSP 设备信息上报任务(升级前的设备状态同步)