杰理 SDK 文档中心
首页
首页
  • 快速开始

    • 环境要求与权限配置
    • 集成SDK依赖
    • 运行示例应用
  • 核心架构与协议

    • RCSP协议与数据通道
    • 蓝牙连接与设备管理
    • TWS双耳功能
    • 基础功能接口与自定义命令
  • 设备功能控制

    • 设备音乐控制与ID3信息
    • 文件浏览与传输
    • FM收音与发射
    • 灯光控制
    • 闹钟与时间管理
    • 查找设备与防丢
    • ANC与噪声处理
    • 按键功能设置
    • 彩屏仓控制
    • AI翻译
  • 音效与音频处理

    • 均衡器音效调节
    • 录音与语音控制
    • Line-in、SPDIF与声卡功能
    • 音频编解码库
  • 扩展功能库

    • OTA固件升级
    • 数据加密与解密
    • 图片与动图格式转换
  • 示例应用 btsmart

    • 应用架构与界面导航
    • 设备功能适配与数据层
    • 设备配置JSON与资源文件
  • 参考与版本

    • 错误码参考
    • 版本历史与更新日志
    • 开发文档中心导航

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_ota AAR)与 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 服务器"]

架构分层说明:

  1. UI 层:FirmwareOtaFragment 实现 IOtaView,通过 FirmwareOtaAdapter 展示升级阶段列表;FirmwareOtaItem 作为多布局列表条目承载阶段信息。
  2. Presenter 层:OtaPresenterImpl 实现 IOtaPresenter,串联"查版本 → 判断 → 下载 → 升级"的业务编排,并将 OTA 库回调转发为 IOtaView 的视图事件。
  3. 桥接层:OTAManager 是核心适配器,把 RCSP 的蓝牙连接、GATT、数据收发能力注入 BluetoothOTAManager,并管理 OTA 前后的设备地址记录(ReconnectAddress)。
  4. 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 接口)或 requestOTAFileonOtaMessageChange / onGetOtaMessageError
judgeDeviceNeedToOta(device, message)委托 OTAManager.judgeDeviceNeedToOta—
downloadFile(url, saveFilePath)调 JL_HttpClient.downloadFileonDownloadStart/Progress/Stop/Error
startFirmwareOta(filePath)校验文件存在 → 设置固件路径 → OTAManager.startOTAonOtaStart / onOtaProgress / onOtaError
cancelFirmwareOta()OTAManager.cancelOTA()onOtaCancel
disconnectDevice()加入忽略列表后由 RCSP 断开—
destroy()复位状态、销毁 RCSP 与 OTAManager、清空 Handler—

升级前的业务处理(mIUpgradeCallback.onStartOTA,OtaPresenterImpl.java#L229-L240):

  1. 标记 MainApplication.setOTA(true),全局标识进入升级态;
  2. 记录当前设备 sdkType;
  3. 若音乐正在播放,调用 PlayControlImpl.pause() 暂停,避免音频流干扰升级通道;
  4. 调用 changeDeviceStatus() 处理单备份(single backup)设备的 OTA 通道地址记录;
  5. 通知视图 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

步骤拆解:

  1. 查询 OTA 服务:Presenter 携带 authKey、projectCode(可选 md5)请求服务器,得到 OtaMessage(含服务器固件版本、下载地址等),成功后回调 onOtaMessageChange。
  2. 版本比较:OTAManager.judgeDeviceNeedToOta 用设备版本码与服务器版本比较,决定是否展示"有新固件"。
  3. 下载固件:downloadFile 通过 HTTP 下载到 saveFilePath,onDownloadStop 时把下载路径设为 upgradeFilePath。
  4. 执行升级:startFirmwareOta 校验文件存在后调用 OTAManager.startOTA,OTA SDK 按配置(SPP 优先、最小 MTU、不使用应用层重连)驱动 RCSP 与设备通信。
  5. 传输与回调:升级过程中 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:

  • OtaPresenterImpl.java#L92-L99
  • OtaPresenterImpl.java#L118-L128

startFirmwareOta 是升级的"守门"方法:先校验固件文件是否存在,否则以 SUB_ERR_FILE_NOT_FOUND 错误码通知视图;通过后再把文件路径注入 OTA 库的 BluetoothOption 并启动升级。

Configuration Options

OTA 传输行为由 BluetoothOTAConfigure 控制,配置集中在 OTAManager.configureOTA():

配置项类型默认值/设定值说明
setPriorityintBluetoothOTAConfigure.PREFER_SPP固件传输通道优先级,SPP(经典蓝牙)优先
setMtuintBluetoothConstant.BLE_MTU_MINBLE MTU 取最小值,保证低端设备兼容
setUseReconnectbooleanfalse不使用 OTA 库内置自动回连,由上层 ReconnectAddress 管理
setUseAuthDevicebooleanfalse不要求设备鉴权
setBleScanModeint2BLE 扫描模式,2 表示高性能搜索
setFirmwareFilePathString按平台选择 .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

方法参数说明
checkFirmwareOtaServiceString authKey, String projectCode[, String md5]查询服务器固件信息;带 md5 走 V2 接口
judgeDeviceNeedToOtaBluetoothDevice, OtaMessage判断设备是否需要升级
downloadFileString url, String saveFilePath下载固件文件到本地
isFirmwareOta—是否正在 OTA(委托 mOTAManager.isOTA())
startFirmwareOtaString filePath开始升级(文件不存在则报 SUB_ERR_FILE_NOT_FOUND)
cancelFirmwareOta—取消升级
disconnectDevice—断开设备并加入弹窗忽略列表
setUpgradeStateint 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 并返回 falseOTAManager.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

  1. 自定义固件判断策略:judgeDeviceNeedToOta 是独立的可覆写方法,可扩展为"版本区间/白名单/灰度"等策略。
  2. OTA 传输配置:configureOTA() 集中了 BluetoothOTAConfigure 的全部参数,如需开启鉴权设备(setUseAuthDevice(true))、调整 MTU 或启用库内回连,只需修改此处。
  3. 固件文件命名:固件文件查找扩展名(.bfu/.ufw)与回退常量(SConstant.FIRMWARE_UPGRADE_FILE / FIRMWARE_UPGRADE_FILE_AC693)定义在常量层,新增固件格式只需扩展该处。
  4. 视图扩展: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 设备信息上报任务(升级前的设备状态同步)
Next
数据加密与解密