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

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

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

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

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

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

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

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

闹钟与时间管理

本文档介绍 Android-JL_Bluetooth(PiHome V1.13.0 / SDK V4.2.0)应用模块(btsmart)中"闹钟"能力的完整实现:从数据模型、蓝牙事件回调、弹窗交互到设备端闹钟的启停控制,并说明时间管理(RTC)能力在系统中所处的位置与边界。

Purpose and Scope

本页面覆盖应用侧闹钟功能的端到端实现:

  • 闹钟数据模型(AlarmBean、AlarmListInfo、DefaultAlarmBell)及其字段语义、重复模式位掩码编码
  • 两条并行的闹钟事件处理链路:新版 RCSP 链路(AlarmHandler + RCSPController)与旧版 BT 链路(AlarmNotifyHandle + BluetoothHelper)
  • 闹钟触发时的 UI 交互(Jl_Dialog 弹窗、停止闹钟操作)及防重复弹窗机制
  • UI 层闹钟列表 / 设置界面(AlarmListFragment、AlarmSettingFragment、AlarmBellContainerFragment)与适配器(AlarmAdapter、AlarmRepeatAdapter、AlarmDefaultBellAdapter)的结构

明确不在本页范围:设备端闹钟固件实现、底层 RCSP 协议报文格式、以及设备系统时间(RTC)的读写命令。时间管理能力由外部蓝牙 SDK(com.jieli.bluetooth 依赖)承载——在 btsmart 模块中未发现独立的系统时间同步入口,相关能力需通过 RCSPController / BluetoothHelper 与设备交互(详见时间管理边界一节)。各铃声管理页面细节属于独立目录页,此处仅说明其在闹钟流程中的衔接。

Overview

闹钟是蓝牙音频设备(耳机 / 音箱)的典型功能:用户通过 App 配置闹钟(时间、重复方式、铃声),配置经蓝牙协议下发到设备端;设备内部 RTC 到点触发闹钟后,通过事件回调通知 App,App 弹出"闹钟进行中"对话框,用户点击确认后 App 再下发停止指令。

仓库中存在两代闹钟实现,体现了一次技术演进的痕迹:

  1. 旧版 BT 链路(AlarmNotifyHandle):继承 BTEventCallback,以单例形式注册到 BluetoothHelper,回调携带 App 层数据模型 AlarmBean / AlarmListInfo。
  2. 新版 RCSP 链路(AlarmHandler):继承 BTRcspEventCallback,构造时注入 RCSPController,回调携带 SDK 层模型 com.jieli.bluetooth.bean.device.alarm.AlarmBean,停止闹钟直接调用 mRCSPController.stopAlarmBell()。

两套链路共享同一个"弹窗交互"设计:以 Fragment tag "alarm_notify" 为唯一标识,保证同一时刻只有一个闹钟提示框;对话框不可取消(cancel(false)),强制用户确认后才能停止闹钟。

关键概念

概念说明
repeatMode闹钟重复模式的位掩码,0x00=不重复、0x01=单次、0xFE=每天,其余为按位表示的星期集合
bellType铃声来源类型:0=默认类型,1=设备文件类型
bellCluster铃声标识:bellType=0 时为铃声序号,bellType=1 时为设备文件簇号
RCSP杰理(Jieli)蓝牙设备远程控制协议,RCSPController 为其 Android 侧封装
硬件闹钟由设备端 RTC 触发的闹钟,App 仅负责配置、提示与停止

Architecture

闹钟功能的代码分层如下图所示——UI 层与数据模型位于 btsmart 模块,事件处理层通过两种回调桥接到外部蓝牙 SDK,最终指令下发到设备。

flowchart TD
    subgraph sg_UI["UI 层 (btsmart)"]
        AlarmListFragment["AlarmListFragment"]
        AlarmSettingFragment["AlarmSettingFragment"]
        AlarmBellContainerFragment["AlarmBellContainerFragment"]
    end

    subgraph sg_Adapter["数据适配层"]
        AlarmAdapter["AlarmAdapter"]
        AlarmRepeatAdapter["AlarmRepeatAdapter"]
        AlarmDefaultBellAdapter["AlarmDefaultBellAdapter"]
    end

    subgraph sg_Model["App 数据模型"]
        AlarmBean["AlarmBean (app)"]
        AlarmListInfo["AlarmListInfo"]
        DefaultAlarmBell["DefaultAlarmBell"]
    end

    subgraph sg_Handler["事件处理层"]
        AlarmHandler["AlarmHandler (RCSP)"]
        AlarmNotifyHandle["AlarmNotifyHandle (旧版 BT)"]
    end

    subgraph sg_SDK["蓝牙 SDK (外部依赖 com.jieli.bluetooth)"]
        RCSPController["RCSPController"]
        BluetoothHelper["BluetoothHelper"]
        SdkAlarmBean["AlarmBean (SDK 模型)"]
    end

    Device["蓝牙设备 (耳机/音箱 RTC)"]

    AlarmListFragment --> AlarmAdapter
    AlarmSettingFragment --> AlarmRepeatAdapter
    AlarmSettingFragment --> AlarmDefaultBellAdapter
    AlarmAdapter --> AlarmBean
    AlarmListFragment --> AlarmListInfo
    AlarmSettingFragment --> AlarmBean
    AlarmBean --> AlarmHandler
    AlarmHandler --> RCSPController
    AlarmNotifyHandle --> BluetoothHelper
    RCSPController --> Device
    BluetoothHelper --> Device
    RCSPController -.->|"onAlarmNotify 回调"| AlarmHandler
    BluetoothHelper -.->|"onAlarmNotify 回调"| AlarmNotifyHandle

分层职责说明

  • UI 层:AlarmListFragment 展示闹钟列表(配合 AlarmAdapter 渲染 AlarmBean);AlarmSettingFragment 提供时间 / 重复 / 铃声设置(配合 AlarmRepeatAdapter 选择星期、AlarmDefaultBellAdapter 选择默认铃声);AlarmBellContainerFragment 承载铃声选择容器。
  • App 数据模型层:AlarmBean(应用侧)是闹钟的完整字段载体,AlarmListInfo 将一组闹钟与 version 打包(用于批量下发/同步),DefaultAlarmBell 描述设备默认铃声。
  • 事件处理层:两条链路分别监听 SDK 事件;AlarmHandler 面向新版 RCSP 协议,AlarmNotifyHandle 是旧版 BT 兼容层。
  • SDK 层:RCSPController(RCSP 协议控制器)与 BluetoothHelper(旧版 BT 帮助类)负责蓝牙连接、指令收发,闹钟触发事件经它们回调到事件处理层。

注意:AlarmHandler 中使用的 AlarmBean 是 SDK 模型(com.jieli.bluetooth.bean.device.alarm.AlarmBean),而 AlarmNotifyHandle 与 UI 适配器使用的是应用模型(com.jieli.btsmart.data.model.bluetooth.AlarmBean)。两代链路的数据模型并不相同,这是迁移期双轨并存的直接证据。

数据模型详解

AlarmBean(应用侧闹钟模型)

com.jieli.btsmart.data.model.bluetooth.AlarmBean 是闹钟功能的核心数据结构,声明于 AlarmBean.java#L16-L43。字段设计体现了"兼容演进"的意图:

字段类型语义
indexbyte闹钟索引(设备端闹钟槽位编号)
nameString闹钟名称
hour / minbyte触发时间(24 小时制时/分)
repeatModebyte重复模式位掩码(见下文编码表)
bellString铃声(已废弃 @Deprecated,仅保留兼容)
reservedString拓展字段
openboolean是否开启
bellTypebyte铃声类型:0=默认类型,1=设备文件类型
bellClusterint铃声簇号:bellType=0 时为铃声序号,bellType=1 时为文件簇号
bellNameString铃声名称(bellType=1 时有效)
devIndexbyte铃声所在设备序号(bellType=1 时有效)
versionint模型版本号

设计要点:

  • 铃声字段的三段式演进:bell(字符串)→ bellType + bellCluster(数值化)→ bellName + devIndex(指向设备文件系统)。新增字段全部以 getter/setter 链式风格扩展,老代码继续编译运行,这是典型的"向前兼容"数据模型设计。
  • copy() 深拷贝(AlarmBean.java#L170-L186):编辑闹钟时先在副本上修改,确认后再整体替换,避免编辑中途把脏数据同步到设备。
  • getRepeatDesc() 静态描述方法(AlarmBean.java#L214-L237):把位掩码翻译成用户可读的"周一、周三"文本,逻辑见下图。

重复模式位掩码编码(repeatMode)

repeatMode 是 1 字节位掩码,getRepeatDesc 的解析顺序如下:

flowchart TD
    Start([getRepeatDesc]) --> Read["读取 repeatMode & 0xff"]
    Read --> IsZero{"mode == 0x00?"}
    IsZero -->|"是"| Empty["空字符串(不重复)"]
    IsZero -->|"否"| IsSingle{"(mode & 0x01) == 0x01?"}
    IsSingle -->|"是"| Single["单次"]
    IsSingle -->|"否"| IsAll{"mode == 0xFE?"}
    IsAll -->|"是"| All["全部"]
    IsAll -->|"否"| Weekly["周 + 逐位解析星期<br/>bit1~bit7 = 一~日"]
    Weekly --> Trim["拼接并替换空格为顿号"]
    Empty --> Trim
    Single --> Trim
    All --> Trim
    Trim --> Result["返回描述文本"]

位掩码取值约定(来源于 AlarmBean.java#L217-L236 的解析逻辑):

值含义
0x00不重复
0x01单次(最低位)
0xFE全部(每天)
其他周重复:bit1~bit7 依次对应周一~周日,逐位右移判断

解析时先判断特殊值(0x00 / 0x01 / 0xFE),再落入通用"周"分支按位展开——这种"特例优先、位掩码兜底"的顺序保证了边界语义不被位运算误读。

AlarmListInfo(闹钟列表包装)

AlarmListInfo 极简地把 version 与 List<AlarmBean> 打包(AlarmListInfo.java#L5-L18)。version 的存在说明列表同步是"带版本号的整体同步"模型:App 与设备各自维护版本,用于判断是否需要重新下发/拉取,从而减少不必要的蓝牙传输。

DefaultAlarmBell(默认铃声)

DefaultAlarmBell 描述设备侧的默认铃声选项,供 AlarmDefaultBellAdapter 渲染"默认铃声"选择列表,对应 bellType=0(默认类型)场景。

事件处理链路

新版 RCSP 链路:AlarmHandler

AlarmHandler 继承 BTRcspEventCallback,构造时注入 RCSPController(AlarmHandler.java#L22-L29)。它重写了三个回调:

  1. onConnection(device, status)(AlarmHandler.java#L35-L41):连接状态变化时若与当前闹钟设备一致,清除 mDevice 并关闭提示框——设备断连即视为闹钟会话结束。
  2. onAlarmNotify(device, alarmBean)(AlarmHandler.java#L43-L47):记录触发闹钟的设备并弹出提示框。
  3. onAlarmStop(device, alarmBean)(AlarmHandler.java#L49-L53):设备侧闹钟停止(可能由设备按键停止),清空设备引用并收起提示框。

停止闹钟的指令是 mRCSPController.stopAlarmBell(getDevice(), null)(AlarmHandler.java#L74),即"先停止设备响铃,再关闭弹窗"的严格顺序。

旧版 BT 链路:AlarmNotifyHandle

AlarmNotifyHandle 继承 BTEventCallback,是双重检查锁的单例(AlarmNotifyHandle.java#L27-L34),内部注释 硬件闹钟 表明其面向设备端 RTC 硬件闹钟。与 RCSP 链路不同,它:

  • 用 AlarmListInfo 重载 onAlarmNotify(AlarmListInfo) 批量打印日志(AlarmNotifyHandle.java#L36-L42);
  • 单个闹钟触发时通过 BluetoothHelper.getInstance().stopAlarm(null) 停止(AlarmNotifyHandle.java#L65);
  • onAlarmStop() 中标注了 //todo 闹钟停止(AlarmNotifyHandle.java#L73-L85),说明旧链路的停止流程仍有待完善的迁移痕迹。

弹窗防重机制

两条链路共用同一套防重复弹窗策略:以 Fragment tag "alarm_notify" 查询 SupportFragmentManager,若已存在则直接返回(AlarmHandler.java#L62-L66、AlarmNotifyHandle.java#L53-L57)。Jl_Dialog.Builder 设置了 cancel(false),用户只能点击"确定"——设计意图是闹钟响铃必须显式确认停止,避免误触返回键导致闹钟无法关闭。

UI 层结构

  • AlarmListFragment:闹钟列表页,通过 AlarmAdapter 渲染,操作入口(新增/编辑/开关)。
  • AlarmSettingFragment:闹钟设置页,时间选择器 + AlarmRepeatAdapter(星期多选)+ 铃声选择(AlarmDefaultBellAdapter 默认铃声 / 设备文件铃声)。
  • AlarmBellContainerFragment:铃声选择容器页,承载默认铃声与设备文件铃声两类子列表。

核心流程:闹钟触发 → 提示 → 停止

以新版 RCSP 链路为例,一次完整的闹钟触发流程如下:

sequenceDiagram
    participant Dev as 蓝牙设备 (RTC)
    participant SDK as RCSPController / 蓝牙 SDK
    participant AH as AlarmHandler
    participant UI as 当前 Activity
    participant Dlg as Jl_Dialog (tag=alarm_notify)

    Dev->>SDK: 设备 RTC 到点,上报闹钟通知
    SDK->>AH: onAlarmNotify(device, alarmBean)
    AH->>AH: setDevice(device)
    AH->>UI: ActivityManager 获取当前 Activity
    alt Activity == null
        UI-->>AH: null → 直接返回(不弹窗)
    else Activity != null
        UI-->>AH: Activity
        AH->>UI: findFragmentByTag("alarm_notify")
        alt 已存在对话框
            AH-->>AH: 返回,防重复弹窗
        else 未显示
            AH->>Dlg: Builder(title=tips, content=alarm_running, cancel=false)
            Dlg-->>UI: show(fragmentManager, "alarm_notify")
            User->>Dlg: 点击"确定"
            Dlg->>AH: rightClickListener 回调
            AH->>SDK: stopAlarmBell(device, null)
            Dlg->>Dlg: dismiss()
        end
    end
    SDK->>AH: onAlarmStop(device, alarmBean)(设备停止或用户操作)
    AH->>AH: setDevice(null)
    AH->>Dlg: dismissNotifyDialog()(兜底关闭)

流程要点:

  1. 触发源在设备端:App 不参与计时,闹钟到点由设备 RTC 决定,App 只响应事件——这保证了即使 App 被杀,闹钟仍会响。
  2. 会话设备记录:AlarmHandler.mDevice 记录触发闹钟的设备,停止指令必须发给同一设备(stopAlarmBell(getDevice(), null))。
  3. 双保险关闭:用户点"确定"主动停止 + onAlarmStop 被动兜底关闭弹窗;连接断开(onConnection)也会清理状态,防止 UI 残留。

旧版 BT 链路(AlarmNotifyHandle)流程完全相同,只是回调来源换成 BluetoothHelper,停止指令换成 stopAlarm(null)。

使用示例(源码摘录)

示例 1:闹钟数据模型与深拷贝

编辑闹钟时先 copy() 一份副本再修改,是 App 侧避免脏数据提前同步的关键模式(AlarmBean.java#L170-L186):

public AlarmBean copy() {
    return new AlarmBean()
            .setIndex(this.getIndex())
            .setHour(this.getHour())
            .setMin(this.getMin())
            .setName(this.getName())
            .setRepeatMode(this.getRepeatMode())
            .setBell(this.getBell())
            .setReserved(this.getReserved())
            .setBellType(this.bellType)
            .setBellName(this.bellName)
            .setBellCluster(this.bellCluster)
            .setVersion(this.version)
            .setDevIndex(this.devIndex)
            .setOpen(this.isOpen());
}

示例 2:重复模式文本描述

把位掩码 repeatMode 翻译为"周 一、三"等用户可读文本(AlarmBean.java#L214-L237):

public static String getRepeatDesc(AlarmBean alarmBean) {
    StringBuilder sb = new StringBuilder();
    String[] dayOfWeek = {"一", "二", "三", "四", "五", "六", "日"};
    int mode = alarmBean.getRepeatMode() & 0xff;
    if (mode == 0x00) {
        sb.append("");
    } else if ((mode & 0x01) == 0x01) {
        sb.append("单次");
    } else if (mode == 0xfe) {
        sb.append("全部");
    } else {
        sb.append("周");
        for (int i = 1; i < 8; i++) {
            int temp = mode;
            temp = temp >> i;
            temp = temp & 0x01;
            if (temp == 0x01) {
                sb.append(dayOfWeek[i - 1]);
                sb.append(" ");
            }
        }
    }
    return sb.toString().trim().replace(" ", "、");
}

示例 3:RCSP 闹钟事件处理与停止指令

AlarmHandler 在闹钟触发时弹窗,用户确认后调用 SDK 停止响铃(AlarmHandler.java#L43-L80):

@Override
public void onAlarmNotify(BluetoothDevice device, AlarmBean alarmBean) {
    setDevice(device);
    showNotifyDialog();
}

@Override
public void onAlarmStop(BluetoothDevice device, AlarmBean alarmBean) {
    setDevice(null);
    dismissNotifyDialog();
}

private void showNotifyDialog() {
    FragmentActivity activity = (FragmentActivity) ActivityManager.getInstance().getCurrentActivity();
    if (activity != null) {
        if (activity.getSupportFragmentManager().findFragmentByTag("alarm_notify") != null) {
            JL_Log.i(tag, "alarm dialog is showing");
            return;
        }
        Jl_Dialog jl_dialog = new Jl_Dialog.Builder()
                .title(activity.getString(R.string.tips))
                .content(activity.getString(R.string.alarm_running))
                .right(activity.getString(R.string.confirm))
                .width(0.8f)
                .cancel(false)
                .rightClickListener((v, dialogFragment) -> {
                    mRCSPController.stopAlarmBell(getDevice(), null);
                    dialogFragment.dismiss();
                })
                .build();
        jl_dialog.show(activity.getSupportFragmentManager(), "alarm_notify");
    }
}

示例 4:旧版 BT 链路单例与批量通知

AlarmNotifyHandle 使用双重检查锁单例,并重载支持整表通知(AlarmNotifyHandle.java#L27-L48):

public static AlarmNotifyHandle getInstance() {
    if (instance == null) {
        synchronized (AlarmNotifyHandle.class) {
            instance = new AlarmNotifyHandle();
        }
    }
    return instance;
}

@Override
public void onAlarmNotify(AlarmListInfo alarmListInfo) {
    super.onAlarmNotify(alarmListInfo);
    for (AlarmBean bean : alarmListInfo.getAlarmBeans()) {
        JL_Log.e(TAG, "onAlarm notify info--> " + bean);
    }
}

@Override
public void onAlarmNotify(AlarmBean alarmBean) {
    super.onAlarmNotify(alarmBean);
    showNotifyDialog();
}

配置项与字段语义

闹钟的"配置"即 AlarmBean 各字段的组合(经蓝牙协议下发到设备),无独立配置文件。关键可配置项如下:

配置项类型默认/取值说明
openbooleanfalse闹钟开关;关闭时设备端不触发
hour / minbyte0–23 / 0–59触发时刻(24 小时制)
repeatModebyte0x00重复模式位掩码:0x00 不重复、0x01 单次、0xFE 每天、其余按位表星期
bellTypebyte00=默认类型;1=设备文件类型
bellClusterint0bellType=0 时为默认铃声序号;bellType=1 时为文件簇号
bellNameStringnull铃声名称(bellType=1 时有效)
devIndexbyte0铃声所在设备序号(bellType=1 时有效,用于多设备场景)
nameString""闹钟名称,getName() 对 null 防御返回空串
reservedStringnull拓展字段,为协议后续演进预留

API 参考

AlarmBean(应用侧模型,com.jieli.btsmart.data.model.bluetooth.AlarmBean)

构造: AlarmBean()(无参,配合链式 setter)

主要方法(均为链式返回 AlarmBean):

  • setIndex(byte index) / getIndex() — 闹钟索引(设备槽位)
  • setName(String name) / getName() — 名称,null 安全
  • setHour(byte hour) / setMin(byte min) / getHour() / getMin() — 触发时间
  • setRepeatMode(byte repeatMode) / getRepeatMode() — 重复位掩码
  • setOpen(boolean open) / isOpen() — 开关状态
  • setBellType(byte) / setBellCluster(int) / setBellName(String) / setDevIndex(byte) — 铃声三元组(类型/簇号/名称/设备序号)
  • setVersion(int) / getVersion() — 模型版本
  • copy() — 深拷贝副本,用于编辑隔离
  • getRepeatDesc(AlarmBean) — 静态,重复模式 → 可读文本
  • toString() — 全字段日志输出(用于 JL_Log.e 调试)

AlarmHandler(RCSP 回调,com.jieli.btsmart.tool.bluetooth.rcsp.AlarmHandler)

  • AlarmHandler(RCSPController controller) — 构造注入控制器
  • getDevice() — 返回当前触发闹钟的 BluetoothDevice
  • onConnection(BluetoothDevice device, int status) — 连接变化:断开则清设备并关弹窗
  • onAlarmNotify(BluetoothDevice device, AlarmBean alarmBean) — 闹钟触发回调
  • onAlarmStop(BluetoothDevice device, AlarmBean alarmBean) — 闹钟停止回调

AlarmNotifyHandle(旧版 BT 回调,com.jieli.btsmart.tool.bluetooth.AlarmNotifyHandle)

  • getInstance() — 双重检查锁单例
  • onAlarmNotify(AlarmListInfo alarmListInfo) — 整表通知(批量日志)
  • onAlarmNotify(AlarmBean alarmBean) — 单闹钟触发 → 弹窗
  • onAlarmStop() — 停止 → 关弹窗

AlarmListInfo(com.jieli.btsmart.data.model.bluetooth.AlarmListInfo)

  • AlarmListInfo(List<AlarmBean> list) / AlarmListInfo(int version, List<AlarmBean> alarmBeans)
  • getAlarmBeans() / setAlarmBeans(List<AlarmBean>)
  • getVersion() / setVersion(int)

故障模式、边界情况与并发

以下行为均能从源码中直接验证:

空 Activity 保护

showNotifyDialog() 先判断 ActivityManager.getInstance().getCurrentActivity() 是否为空(AlarmHandler.java#L60-L61)。App 处于后台/被回收时弹窗会静默跳过,不崩溃——代价是闹钟只能靠设备端响铃提示。

重复弹窗竞态

两条链路(甚至两个链路同时)都可能收到 onAlarmNotify。防重机制依赖 findFragmentByTag("alarm_notify") 检查:若弹窗已显示则直接返回。该检查与 show() 之间无同步锁,但 FragmentManager 本身在主线程串行执行,实际竞态窗口极小。

断连清理

onConnection 中 BluetoothUtil.deviceEquals(device, mDevice) 匹配后清空设备并关弹窗——设备中途断连时,App 不会残留"闹钟进行中"的假状态。

停止指令的幂等性

stopAlarmBell(getDevice(), null) 与 stopAlarm(null) 均带 null 回调;设备已停止闹钟时再次下发停止,由协议层保证无害(App 侧未做额外状态判断,属于对 SDK 的信任)。

旧链路的未完成点

AlarmNotifyHandle.onAlarmStop() 标注 //todo 闹钟停止,且旧链路无 onConnection 清理逻辑——迁移期遗留,建议新功能一律走 AlarmHandler。

时间管理边界(RTC)

本仓库 btsmart 模块没有独立的系统时间设置/同步页面:闹钟的"到点触发"完全依赖设备端 RTC 硬件,App 侧不参与计时。设备时间(RTC)的读取与校准属于底层蓝牙 SDK(com.jieli.bluetooth)的 RCSP 协议能力范畴——RCSPController 是访问该类能力的统一入口;如需在 App 层增加"校时"功能,应扩展 BTRcspEventCallback 子类(模式与 AlarmHandler 相同)并复用 AlarmBean 的 version 字段做设备端时间版本协商。

性能与运维提示

  • 弹窗开销:Jl_Dialog 宽度固定 0.8f,生命周期短,无性能热点。
  • 日志:闹钟触发时 AlarmNotifyHandle 对整表 AlarmBean 逐条 JL_Log.e,在多闹钟设备上会一次输出多条日志,可用于线上排查"闹钟未弹窗"问题。
  • 内存:AlarmNotifyHandle 为全局单例,随进程常驻;AlarmHandler 由 RCSP 控制器持有,二者均无显式释放,属于长期存活组件。
  • 蓝牙传输:闹钟列表带 version 整体同步,修改单个闹钟时优先考虑增量下发以节省带宽。

扩展点

  1. 新增闹钟回调:继承 BTRcspEventCallback,仿照 AlarmHandler 注入 RCSPController,即可接入更多设备事件(如铃声播放状态)。
  2. 铃声扩展:通过 bellType=1 + bellCluster + bellName + devIndex 四元组指向设备文件系统,AlarmBellContainerFragment 是接入自定义铃声列表的 UI 挂载点。
  3. 多设备支持:devIndex 字段表明闹钟铃声可来自多设备场景,mDevice 会话记录模式可推广到其他按设备区分的功能。
  4. 协议兼容:reserved 字段与 version 字段为协议演进预留,新增字段时保持链式 setter 风格即可向后兼容。

相关链接

  • AlarmBean.java(应用侧模型)
  • AlarmListInfo.java
  • AlarmHandler.java(RCSP 链路)
  • AlarmNotifyHandle.java(旧版 BT 链路)
  • AlarmListFragment.java(列表 UI)
  • AlarmSettingFragment.java(设置 UI)
  • AlarmBellContainerFragment.java(铃声容器 UI)
  • DefaultAlarmBell.java

注:铃声选择、设备文件管理等细节见对应的铃声管理目录页;蓝牙连接与协议封装见蓝牙 SDK 相关页面。

Prev
灯光控制
Next
查找设备与防丢