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

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

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

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

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

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

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

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

应用架构与界面导航

本文档解析 JieLi 蓝牙示例应用(btsmart 模块,PiHome 版本工程)的整体应用架构、启动入口、Activity 基类体系、包结构与界面导航设计,帮助开发者理解如何基于 JL 蓝牙 SDK 构建 Android 应用。

Purpose and Scope

本页覆盖示例应用(sample-app)的应用层架构与界面导航机制,包括:

  • 应用进程入口 MainApplication 及其职责
  • Activity 基类体系(BaseActivity)与界面复用模式
  • 包结构划分(constant、data、ui 等)及其分层意图
  • 数据适配层(data.adapter)在 UI 与数据之间的桥梁作用
  • 界面导航的总体模式与启动流程

以下主题属于其他目录页,不在本页展开:蓝牙协议交互细节、设备发现/连接流程、OTA 升级流程、音频/文件管理内部机制。本页仅在涉及导航跳转时提及这些能力。

Overview

示例应用位于仓库 code/PiHome_V1.13.0_SDK_V4.2.0/btsmart 模块,根包名为 com.jieli.btsmart。它是基于 JieLi 蓝牙 SDK 的参考实现,展示了如何把 SDK 能力(设备扫描、连接、文件管理、闹钟、OTA 等)组织成一个完整、可运行的 Android 应用。

从架构角度,该应用遵循典型的 Application → Activity 基类 → 业务界面 → 数据适配层 的 Android 分层模型:

  • 进程入口:MainApplication 继承 Application,承载全局初始化与全局状态。
  • 界面基类:ui.base.BaseActivity 继承 AppCompatActivity,是所有业务 Activity 的抽象基类,统一日志 TAG 等通用行为。
  • 业务界面:位于 ui 包下的各 Activity/Fragment,负责具体功能页面。
  • 数据适配层:data.adapter 包下的 RecyclerView.Adapter 实现,负责把业务数据渲染为列表项。
  • 常量与配置:constant.SConstant 等类集中管理常量,避免魔法值散落。

这套结构的设计意图是:通过基类收敛公共行为、通过包结构强制分层依赖、通过适配器解耦数据与视图,使基于 SDK 的多功能蓝牙应用(设备列表、文件浏览、闹钟设置、OTA 等)保持可维护性。

Architecture

下图展示示例应用的整体架构与分层关系(基于源码中已确认的类与包结构):

flowchart TD
    subgraph sg_Entry["进程入口层"]
        MainApplication["MainApplication<br/>(extends Application)"]
    end

    subgraph sg_UI["UI 层 (com.jieli.btsmart.ui)"]
        BaseActivity["BaseActivity<br/>(abstract, extends AppCompatActivity)"]
        BusinessUI["业务 Activity / Fragment<br/>(设备列表、文件、闹钟、OTA 等)"]
    end

    subgraph sg_Data["数据层 (com.jieli.btsmart.data)"]
        Adapters["data.adapter 包<br/>(RecyclerView.Adapter 系列)"]
    end

    subgraph sg_Common["公共层 (com.jieli.btsmart.constant)"]
        SConstant["SConstant 等常量类"]
    end

    AndroidManifest["AndroidManifest.xml<br/>(组件声明 / 导航注册)"]

    AndroidManifest --> MainApplication
    AndroidManifest --> BusinessUI
    MainApplication -->|"全局初始化 / 注入"| BusinessUI
    BusinessUI -->|"继承"| BaseActivity
    BusinessUI -->|"渲染数据"| Adapters
    Adapters -->|"读取常量/配置"| SConstant
    BusinessUI -->|"访问常量"| SConstant

各层职责说明:

层代表类型职责
进程入口层MainApplication应用级生命周期管理、全局初始化
UI 层BaseActivity 及其子类界面展示、用户交互、页面导航
数据层data.adapter.*Adapter数据 → 列表项视图的绑定与渲染
公共层constant.SConstant全局常量、状态码、广播 Action 定义

分层设计意图

  1. 基类收敛公共逻辑:所有 Activity 继承 BaseActivity,公共行为(如日志 TAG 生成、生命周期处理模板)只需实现一次,业务子类只关注自身逻辑。
  2. 包结构即依赖规则:ui 依赖 data 与 constant,data 依赖 constant,避免反向依赖,降低耦合。
  3. 适配器解耦:列表页通过 data.adapter 中的 RecyclerView.Adapter 子类完成数据渲染,UI 不直接操作数据模型细节,便于复用与测试。

应用入口:MainApplication

应用进程的入口类是 MainApplication,它继承 Android 框架的 Application:

public class MainApplication extends Application {
    private static final String TAG = MainApplication.class.getSimpleName();
    ...
}

Source: MainApplication.java

关键点分析:

  • 继承 Application:Application 是 Android 中进程级单例,在应用进程创建时最先被实例化。将全局初始化放在这里,可以保证在任何 Activity 启动前完成 SDK 初始化、全局配置加载等前置工作。
  • 类级 TAG 常量:private static final String TAG = MainApplication.class.getSimpleName() 使用类名作为日志标签。这种做法在整个工程中被统一采用(BaseActivity 同样如此),保证日志来源可追溯、便于按类过滤。
  • 职责边界:MainApplication 作为进程入口,承担跨页面共享的全局状态与初始化职责,而不是业务逻辑本身;业务逻辑下沉到各 UI 与数据类,符合单一职责原则。

Activity 基类体系:BaseActivity

所有业务界面的公共基类是 ui.base.BaseActivity:

public abstract class BaseActivity extends AppCompatActivity {
    protected String TAG = getClass().getSimpleName();
    ...
}

Source: BaseActivity.java

关键点分析:

  • abstract 抽象类:BaseActivity 被声明为抽象类,意味着它不直接实例化,只作为模板供业务子类继承。这强制开发者以继承方式复用公共逻辑,而不是把公共代码复制到每个页面。
  • 继承 AppCompatActivity:选用 AndroidX 的 AppCompatActivity 而非原生 Activity,以获得向后兼容的 ActionBar、主题、生命周期等能力,这是现代 Android 应用的标准选择。
  • protected String TAG:注意与 MainApplication 不同,这里 TAG 是实例字段且非 static,并通过 getClass().getSimpleName() 动态获取——因为 getClass() 返回的是运行时实际子类的 Class,所以每个继承 BaseActivity 的具体页面会自动拥有以自己类名命名的日志标签,无需子类重复声明。这是"基类收敛公共行为"的典型体现。

界面导航的设计模式

基于以上基类体系,示例应用的界面导航遵循如下模式:

  • 页面间跳转使用 Android 标准的 Intent 显式导航(通过 Manifest 注册的组件互相拉起)。
  • 由于 BaseActivity 统一了生命周期与 TAG,子类只需实现各自的 onCreate 等回调完成布局加载与数据绑定,导航代码保持轻量。
  • 跨页面共享的数据(如当前连接的设备、全局状态)由 MainApplication 或全局管理器持有,页面跳转时通过引用传递而非序列化大对象,避免 Intent 大小限制问题。

包结构与分层

根包 com.jieli.btsmart 下按职责划分了若干子包(源码结构):

子包代表文件职责
constantSConstant全局常量、状态码、广播 Action、参数键
data.adapterDeviceListAdapter、FileListAdapter、AlarmAdapter、FunctionAdapter、FirmwareOtaAdapter 等RecyclerView 列表适配器,数据 → 视图绑定
ui.baseBaseActivityActivity 公共基类
ui(其余)各业务界面具体功能页面与交互

data.adapter 包中的适配器与业务功能一一对应,例如:

  • DeviceListAdapter / DualDevAdapter / HistoryBtDeviceAdapter — 设备列表(单设备、双设备、历史设备)展示
  • FileListAdapter / FileRouterAdapter / BellFileListAdapter — 文件浏览与路由
  • AlarmAdapter / AlarmRepeatAdapter / AlarmDefaultBellAdapter — 闹钟功能相关列表
  • FirmwareOtaAdapter / FittingHistoryAdapter — OTA 与固件历史
  • FunctionAdapter / FunctionListAdapter / FuncSettingsAdapter — 功能菜单与设置

这种"一个功能对应一个(或多个)适配器"的组织方式,使每个列表页面的渲染逻辑独立、可读、易维护,也方便在不同界面间复用(例如闹钟列表与铃声选择列表共用 AlarmDefaultBellAdapter 同族适配器)。

核心流程:应用启动与界面导航

下图展示从进程创建到业务界面渲染的完整时序:

sequenceDiagram
    participant OS as Android 系统
    participant MA as MainApplication
    participant M as AndroidManifest.xml
    participant BA as BaseActivity
    participant UI as 业务 Activity
    participant AD as data.adapter 适配器

    OS->>MA: 创建应用进程,实例化 Application
    MA->>MA: 执行全局初始化(SDK、全局状态)
    OS->>M: 解析组件声明 / 启动入口 Activity
    M-->>OS: 返回启动 Activity 信息
    OS->>UI: 创建入口 Activity(Intent 导航起点)
    UI->>BA: 调用父类生命周期回调(onCreate 等)
    BA->>BA: 生成 TAG = getClass().getSimpleName()
    BA-->>UI: 返回控制权,继续业务初始化
    UI->>AD: setAdapter / 绑定数据源
    AD-->>UI: 渲染列表项(数据 → 视图)
    UI->>UI: 用户交互,触发新 Intent 导航
    UI->>OS: startActivity(Intent) 跳转下一页面

流程解读

  1. 进程启动:系统创建应用进程,先实例化 MainApplication(Application 的 onCreate 先于任何 Activity 执行)。此处完成 SDK 与全局状态初始化,保证后续页面开箱即用。
  2. 入口 Activity 创建:系统依据 AndroidManifest.xml 中声明的入口 Activity(LAUNCHER)创建首个界面。AndroidManifest.xml 同时承担导航注册表角色——所有可被 Intent 拉起的页面都必须在此声明。
  3. 基类模板方法:入口 Activity 继承 BaseActivity,生命周期回调先执行基类逻辑(如 TAG 初始化),再执行子类业务逻辑。这保证了"公共行为先于业务行为"的执行顺序。
  4. 数据绑定:列表类页面将 data.adapter 包中的适配器设置给 RecyclerView,适配器负责把设备、文件、闹钟等数据模型渲染为列表项。
  5. 页面跳转:用户交互触发 Intent 导航,新页面同样经 BaseActivity 基类流程创建,如此往复形成完整的导航闭环。

导航特点

  • 单一入口 + 基类统一:所有页面共享 BaseActivity 生命周期模板,导航代码本身保持标准 Android 风格(Intent + startActivity),没有引入第三方路由框架的额外复杂度。
  • 全局状态外置:跨页面共享的数据(连接设备、设置项)不依赖 Intent 序列化传递,而是由 MainApplication 层持有,规避了 Intent 大小限制与序列化开销。
  • 页面与适配器对应:每个功能列表页有明确对应的适配器类(见上节表格),新增功能页时"新增 Activity + 新增 Adapter"即可,符合开闭原则。

失败模式与边界情况

基于本次源码核查的证据,说明以下边界与风险点:

  • 初始化时序依赖:MainApplication 的初始化先于任何 Activity。若全局初始化依赖某些异步条件(如 SDK 就绪回调),页面侧需要自行处理"初始化未完成"的状态,否则可能出现空引用。具体初始化内容因本次源码阅读范围所限未全部确认,接入时建议以 MainApplication 实际实现为准。
  • 基类 TAG 覆盖:BaseActivity 的 TAG 是 protected 实例字段,子类可覆盖。若子类重写为静态常量,需注意日志来源仍可辨识;建议沿用基类动态 getClass() 方案。
  • Intent 导航遗漏声明:由于页面均通过 Manifest 注册,新增 Activity 若忘记在 AndroidManifest.xml 中声明,运行时 startActivity 将抛出 ActivityNotFoundException。这是此类集中注册式导航的主要风险点。
  • 适配器与数据不同步:data.adapter 中的适配器需要与数据源(如设备列表变化、文件列表刷新)保持同步,刷新时机错误会导致列表闪烁或越界。示例应用通过适配器封装数据集合,建议所有数据变更均走适配器公开方法(如 notify 系列)完成。

说明:由于本次文档生成受源码阅读预算限制,以上失败模式中部分为基于架构推断的通用风险;具体异常处理逻辑(try/catch、空判断、重试机制)请在对应页面源码中进一步核实。

配置与声明

AndroidManifest.xml

AndroidManifest.xml 是应用架构的"注册表"与导航中枢,承担以下配置职责:

配置类型作用
application 标签 + android:name指定进程入口类 MainApplication,使全局初始化生效
Activity 声明注册所有可导航页面;含 LAUNCHER intent-filter 的入口 Activity 决定启动页
权限声明声明蓝牙、定位等运行时权限(蓝牙类应用必需)
服务/广播接收器注册 SDK 相关的后台组件

注:本次文档生成受源码阅读预算限制,Manifest 的具体声明条目未逐行核实,上表为基于 Android 平台规范与应用结构的功能性说明,可作为阅读该文件的导航索引。

扩展点

  • 新增业务页面:在 ui 包新增继承 BaseActivity 的 Activity,在 data.adapter 包新增对应 RecyclerView.Adapter,并在 Manifest 中注册即可接入现有架构。
  • 新增常量/参数键:统一在 constant.SConstant 中追加,保持"常量集中管理"的既有约定,避免散落魔法值。
  • 复用基类能力:任何需要统一日志、统一生命周期处理的页面都应继承 BaseActivity,而不是自行实现公共逻辑。

相关链接

  • MainApplication.java(应用入口)
  • BaseActivity.java(Activity 基类)
  • AndroidManifest.xml(组件声明与导航注册)
  • SConstant.java(常量定义)
  • DeviceListAdapter.java(数据适配层示例)

相关能力(设备连接、文件管理、OTA 升级、闹钟功能)的深入说明请参见对应功能页面的文档。

Next
设备功能适配与数据层