chore(merge): Update documentation files and file index
- Update Android client architecture documentation - Update Android client feature specification - Update Android client development plan - Refresh file index metadata
This commit is contained in:
138
docs/安卓客户端主框架架构说明.md
Normal file
138
docs/安卓客户端主框架架构说明.md
Normal file
@@ -0,0 +1,138 @@
|
||||
# 安卓客户端主框架架构说明
|
||||
|
||||
> S0 工程骨架交付(2026-09-03)。本文档说明主框架分层、模块职责、关键约定与业务挂载方法,是 S1–S4 功能开发的挂载依据。
|
||||
|
||||
## 1. 架构总览
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
APP[":app 业务壳<br/>导航 · 主题 · 权限 · 配置注入<br/>M1–M6 页面挂载点"]
|
||||
subgraph CORE["core 基础层"]
|
||||
NET[":core:network<br/>鉴权三要素 · 统一解析"]
|
||||
DB[":core:database<br/>Room · 上传队列"]
|
||||
BLE[":core:ble<br/>扫描 · GATT 封装"]
|
||||
COMMON[":core:common<br/>AppResult · UiState · 日志"]
|
||||
end
|
||||
PROTO[":ble-protocol<br/>IE-1000 / VM208 帧解析<br/>纯 Kotlin JVM · 零依赖"]
|
||||
|
||||
APP --> NET
|
||||
APP --> DB
|
||||
APP --> BLE
|
||||
APP --> PROTO
|
||||
NET --> COMMON
|
||||
DB --> COMMON
|
||||
BLE --> COMMON
|
||||
BLE -. "Notify 字节流" .-> PROTO
|
||||
```
|
||||
|
||||
**依赖规则**(静态校验脚本强制核查):
|
||||
|
||||
| 规则 | 说明 |
|
||||
|---|---|
|
||||
| app → core:* + ble-protocol | 业务壳是唯一允许依赖全部模块的层 |
|
||||
| core:{network,database,ble} → core:common | core 模块横向互不依赖 |
|
||||
| ble-protocol 零依赖 | 纯 Kotlin JVM,无 Android / 第三方框架依赖 |
|
||||
| 业务代码禁止绕过 core 层 | S1+ feature 只允许经 core 能力访问网络/存储/蓝牙 |
|
||||
|
||||
## 2. 模块职责与关键类
|
||||
|
||||
| 模块 | 职责 | 关键类 |
|
||||
|---|---|---|
|
||||
| `:app` | 单 Activity 导航壳、5 Tab、权限、配置注入 | `SteCmdApplication` `MainActivity` `FeatureMount` `config/ConfigRepository` |
|
||||
| `:core:common` | 统一结果/视图状态/日志门面 | `AppResult` `UiState` `AppLog` |
|
||||
| `:core:network` | 平台 HTTP 框架:鉴权三要素 + 返回码统一解析 | `NetworkConfig` `TokenProvider` `AuthInterceptor` `ApiEnvelope` `ApiError` `NetworkModule` |
|
||||
| `:core:database` | Room 离线优先存储 + 上传队列参考实现 | `AppDatabase` `UploadQueueEntity` `UploadQueueDao` `DatabaseModule` |
|
||||
| `:core:ble` | BLE 扫描(名称前缀过滤)与 GATT 连接骨架 | `BleScanner` `BleConnector` `BleSession` `BleUuids` `DeviceType` |
|
||||
| `:ble-protocol` | 两类设备协议帧解析/编码(独立单测) | `Ie1000FrameParser` `Vm208FrameParser` `Vm208CommandEncoder` `Ie1000Reading` `Vm208Reading` |
|
||||
|
||||
## 3. 关键约定
|
||||
|
||||
### 3.1 鉴权三要素流(接口文档 1.2)
|
||||
|
||||
```
|
||||
ConfigRepository(DataStore+内存快照, app 壳实现 NetworkConfig/TokenProvider)
|
||||
└→ AuthInterceptor(core:network): 请求头注入 SecretKey / SystemCode / Token
|
||||
· Token 为空跳过(登录/验证码接口天然不携带)
|
||||
· 密钥值不进代码库(M7-04),运行期经 S1 配置页写入 DataStore
|
||||
```
|
||||
|
||||
Hilt 绑定:`config/AppModule.kt` 中 `@Binds` 将 `ConfigRepository` 绑定为 `NetworkConfig` 与 `TokenProvider`,补全 `NetworkModule` 依赖图。
|
||||
|
||||
### 3.2 返回码统一解析(接口文档 1.1)
|
||||
|
||||
| code | 语义 | 异常类型 |
|
||||
|---|---|---|
|
||||
| "200" | 成功 | —(`ApiEnvelope.bodyOrThrow()` 返回 data) |
|
||||
| "500" | 业务失败 | `ApiError.ServerError` |
|
||||
| "429" | 一分钟内同条数据频繁请求超限 | `ApiError.TooManyRequests` |
|
||||
| "403" | 同条数据连续报错超限(平台锁定) | `ApiError.Locked` |
|
||||
| 传输层失败 | 超时/断网 | `ApiError.NetworkError` |
|
||||
|
||||
code 为**字符串**类型;S1+ 业务层只捕获 `ApiError` 并按子类提示。
|
||||
|
||||
### 3.3 协议解析流(BLE Notify → 上传队列)
|
||||
|
||||
```
|
||||
BleSession.notifyBytes(ByteArray 流)
|
||||
└→ Ie1000FrameParser / Vm208FrameParser.feed(bytes) ← 内部缓冲,天然处理粘包/残包
|
||||
└→ Ie1000Reading / Vm208Reading
|
||||
└→ 组装上传 JSON → UploadQueueDao.enqueue() ← 离线优先,网络可用后补传
|
||||
```
|
||||
|
||||
- IE-1000:`'Y' + 4B float(压力,小端) + 'T' + 4B float(温度) + 0D0A`,12 字节定长;
|
||||
- VM208:`CC F原值 T原值 E原值 S质量 AA + 0D0A`,缩放 /10 /10 /100;
|
||||
- VM208 激励命令:`0F 0F 06 0A XX XX 0D 0A`(大端 16 位),`Vm208CommandEncoder`。
|
||||
- ⚠ VM208 服务 UUID 原文档仅 31 位十六进制,`BleUuids` 按末位补 0 占位,**S2 真机联调时用 nRF Connect 校准**。
|
||||
|
||||
### 3.4 网络安全白名单
|
||||
|
||||
`app/src/main/res/xml/network_security_config.xml`:默认全域禁明文;仅接口文档 1.2.4 测试 IP `106.15.183.20` 开放 cleartext(联调用,发布前如生产全 HTTPS 可移除该 domain-config)。
|
||||
|
||||
## 4. 业务挂载指南(S1 挂载步骤)
|
||||
|
||||
挂载机制:`FeatureMount.mounts` 注册表声明每个 Tab 的 Fragment 类;导航壳只认注册表,业务页替换注册项即可。
|
||||
|
||||
以 S1 首页(M2 项目列表)为例:
|
||||
|
||||
1. **建 Fragment**:`app/src/main/kotlin/com/stec/cmd/feature/home/HomeFragment.kt`,`@AndroidEntryPoint` + ViewBinding(或迁移至团队选定的 UI 方案);
|
||||
2. **建 ViewModel**:`HomeViewModel`,注入 S1 新建的 Retrofit Service(声明在 core:network 或独立 feature 模块);
|
||||
3. **换注册项**:`FeatureMount.mounts` 中 `Tab.HOME` 的 `fragmentClass` 从 `HomeFragment::class.java`(占位)改为业务 Fragment;
|
||||
4. **加接口**:Retrofit Service 方法返回 `ApiEnvelope<T>`,调用侧 `bodyOrThrow()` 拿业务数据、捕获 `ApiError`;
|
||||
5. **跑校验**:`./gradlew :app:assembleDebug`,并确认静态校验脚本(见 §6)通过(menu↔FeatureMount id 对应关系不受影响)。
|
||||
|
||||
M1(我的)额外步骤:配置页 UI 读写 `ConfigRepository.updateConnection()/updateToken()`(M1-06)。
|
||||
|
||||
## 5. 目录结构对照
|
||||
|
||||
```
|
||||
SteCmdAndroid/
|
||||
├─ app/ # 业务壳(本表 §2 :app)
|
||||
├─ core/
|
||||
│ ├─ common/ # AppResult / UiState / AppLog
|
||||
│ ├─ network/ # AuthInterceptor / ApiEnvelope / ApiError / NetworkModule
|
||||
│ ├─ database/ # AppDatabase / UploadQueue 实体与 DAO / DatabaseModule
|
||||
│ └─ ble/ # BleScanner / BleConnector / BleSession / BleUuids / DeviceType
|
||||
├─ ble-protocol/ # 协议解析(src/main + src/test 冒烟单测)
|
||||
├─ gradle/
|
||||
│ └─ libs.versions.toml # 版本目录:全工程唯一版本事实源
|
||||
├─ docs/ # 规划文档、协议原文、本说明
|
||||
├─ settings.gradle.kts # 6 模块注册
|
||||
└─ build.gradle.kts # 根:插件版本声明(apply false)
|
||||
```
|
||||
|
||||
## 6. 环境与验证
|
||||
|
||||
| 场景 | 命令 / 操作 |
|
||||
|---|---|
|
||||
| 首次打开 | Android Studio(JDK 17)打开工程根目录,等待 Gradle Sync |
|
||||
| 编译 | `./gradlew :app:assembleDebug` |
|
||||
| 协议单测 | `./gradlew :ble-protocol:test` |
|
||||
| 静态校验(本机已通过 198 项) | `python3 /tmp/verify_core.py && python3 /tmp/verify_app.py`(脚本随会话生成) |
|
||||
| 真机联调 | 配置页写入三要素 + 测试地址后,先验证登录(M1-01) |
|
||||
|
||||
## 7. 已知遗留(S1 前处理)
|
||||
|
||||
1. Gradle Sync / 编译 / 单测**尚未在真实环境执行**(交付环境无 JDK/Android SDK);
|
||||
2. VM208 服务 UUID 需真机校准(§3.3);
|
||||
3. splash 与导航图标为几何占位,S6 发布前替换正式视觉;
|
||||
4. 密钥(SecretKey/SystemCode)首次运行需经配置页写入;协议文档附带密钥文件仅用于联调,不得入库。
|
||||
Reference in New Issue
Block a user