a57692353c
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
238 lines
9.6 KiB
Markdown
238 lines
9.6 KiB
Markdown
# 02 — 交互流程与导航设计
|
||
|
||
> **核心原则**:间接启动(语音/手势)不进入全屏 APP,而是以悬浮覆盖层呈现
|
||
> **关联文档**:[01-voice-assistant-system.md](01-voice-assistant-system.md)
|
||
|
||
---
|
||
|
||
## 1. 启动来源 → 界面模式 映射表
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ 启动来源 │
|
||
├───────────────────────┬──────────────────────────────────┤
|
||
│ 直接启动 (Explicit) │ 间接启动 (Implicit) │
|
||
├───────────────────────┼──────────────────────────────────┤
|
||
│ · 桌面图标 │ · 语音唤醒 ("昔涟") │
|
||
│ · 最近任务列表 │ · 长按 Home 键 │
|
||
│ · 通知栏点击 │ · 底部两角向内滑动 │
|
||
│ · Deep Link │ · 长按电源键 (配置后) │
|
||
│ │ · 耳机按键 (单击/长按) │
|
||
│ │ · 锁屏右滑助手 │
|
||
├───────────────────────┼──────────────────────────────────┤
|
||
│ ▼ │ ▼ │
|
||
│ 全屏 Activity │ VoiceInteractionSession │
|
||
│ (MainActivity) │ (全屏悬浮覆盖层) │
|
||
│ · 完整导航栏 │ · 无导航栏 │
|
||
│ · Tab 切换 │ · 仅对话卡片 │
|
||
│ · 设置/IoT 面板 │ · 半透明遮罩透出底层 │
|
||
│ · 压入返回栈 │ · 不压入返回栈 │
|
||
└───────────────────────┴──────────────────────────────────┘
|
||
```
|
||
|
||
## 2. 全屏 Activity 模式
|
||
|
||
### 2.1 导航结构
|
||
|
||
```
|
||
MainActivity
|
||
├── BottomNavigation
|
||
│ ├── Tab 1: 对话 (ChatScreen) ← 默认页
|
||
│ ├── Tab 2: IoT 面板 (IoTScreen)
|
||
│ └── Tab 3: 我的 (ProfileScreen)
|
||
├── TopAppBar
|
||
│ ├── 昔涟状态指示器 (在线/思考中/离线)
|
||
│ └── 快捷操作 (设置、通知)
|
||
└── 子页面 (通过 NavHost 导航)
|
||
├── SettingsScreen
|
||
├── MemoryScreen (记忆查看)
|
||
├── KnowledgeScreen (知识库)
|
||
├── AutomationScreen (自动化规则)
|
||
├── ReminderScreen (提醒列表)
|
||
└── LoginScreen
|
||
```
|
||
|
||
### 2.2 导航图 (NavGraph)
|
||
|
||
```
|
||
LoginScreen ──(登录成功)──► MainScreen (带 BottomNav)
|
||
│
|
||
┌────────────┼────────────┐
|
||
▼ ▼ ▼
|
||
ChatScreen IoTScreen ProfileScreen
|
||
│ │
|
||
▼ ▼
|
||
MemoryScreen SettingsScreen
|
||
KnowledgeScreen ├─ Account
|
||
AutomationScreen ├─ Appearance (主题)
|
||
ReminderScreen ├─ Voice (唤醒词/语音)
|
||
├─ IoT Config
|
||
└─ About
|
||
```
|
||
|
||
### 2.3 登录流程
|
||
|
||
```
|
||
APP 首次启动
|
||
→ 检查本地 Token
|
||
├─ 有效 → 直接进入 MainScreen
|
||
└─ 无效 → LoginScreen
|
||
├─ 输入 Gateway 地址 + 账号密码
|
||
├─ POST /api/v1/auth/login
|
||
├─ 保存 Token 到 DataStore
|
||
└─ 进入 MainScreen
|
||
```
|
||
|
||
## 3. 悬浮覆盖层模式 (VoiceInteractionSession)
|
||
|
||
### 3.1 视觉层级
|
||
|
||
```
|
||
┌──────────────────────────────────────┐
|
||
│ 底层 APP (半透明可见) │
|
||
│ ┌──────────────────────────────┐ │
|
||
│ │ 半透明黑色遮罩 (80% 不透明度) │ │
|
||
│ │ │ │
|
||
│ │ ┌──────────────────────┐ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ 对话卡片区域 │ │ │
|
||
│ │ │ (圆角顶部 28dp) │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ │ · 昔涟状态条 │ │ │
|
||
│ │ │ · 对话消息流 │ │ │
|
||
│ │ │ · 文本输入框 │ │ │
|
||
│ │ │ · 语音输入按钮 │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ └──────────────────────┘ │ │
|
||
│ │ │ │
|
||
│ └──────────────────────────────┘ │
|
||
└──────────────────────────────────────┘
|
||
```
|
||
|
||
### 3.2 覆盖层生命周期
|
||
|
||
```
|
||
Trigger (唤醒词/手势/按键)
|
||
│
|
||
▼
|
||
VoiceInteractionSession.onCreateContentView()
|
||
│
|
||
▼
|
||
onShow() → 设置窗口属性 → 播放出现动画(底部滑入)
|
||
│
|
||
▼
|
||
OverlayScreen Compose 渲染
|
||
│
|
||
├→ 用户说话 → STT → 显示识别文本 → 发送到 AI-Core
|
||
│ │
|
||
│ ▼
|
||
│ SSE 流式响应
|
||
│ │
|
||
├← TTS 语音播放 ←── 流式合成 ←────────────┘
|
||
│
|
||
├→ 用户打字输入 → WebSocket 发送 → 显示回复气泡
|
||
│
|
||
▼
|
||
对话结束
|
||
├→ 用户主动关闭 (说"再见"/点击遮罩/下滑)
|
||
└→ 超时自动关闭 (静默 10 秒)
|
||
│
|
||
▼
|
||
onHide() → 播放消失动画(底部滑出)
|
||
│
|
||
▼
|
||
finish() → 返回触发前界面
|
||
```
|
||
|
||
### 3.3 覆盖层状态机
|
||
|
||
```
|
||
┌──────────┐
|
||
│ IDLE │ (覆盖层不可见)
|
||
└────┬─────┘
|
||
│ 触发
|
||
▼
|
||
┌──────────┐
|
||
│LISTENING │ (等待语音输入,波形动画)
|
||
└────┬─────┘
|
||
│ 检测到语音 / 用户开始打字
|
||
▼
|
||
┌──────────┐
|
||
│PROCESSING│ (STT 识别中 / LLM 思考中)
|
||
└────┬─────┘
|
||
│ 收到回复
|
||
▼
|
||
┌──────────┐
|
||
│SPEAKING │ (TTS 播放中)
|
||
└────┬─────┘
|
||
│ 播放完毕,等待下一轮
|
||
▼
|
||
┌──────────┐
|
||
│ WAITING │ (等待用户继续或关闭)
|
||
└────┬─────┘
|
||
│
|
||
┌───────┼───────┐
|
||
│ │
|
||
用户继续说话 10s 静默
|
||
│ │
|
||
▼ ▼
|
||
LISTENING IDLE
|
||
(覆盖层关闭)
|
||
```
|
||
|
||
### 3.4 与全屏 Activity 的切换
|
||
|
||
```
|
||
悬浮窗中用户点击 "打开完整 APP"
|
||
→ finish() 关闭悬浮窗
|
||
→ startActivity(MainActivity)
|
||
→ 用户在全屏模式下继续操作
|
||
|
||
全屏 APP 中用户按 Home 返回桌面
|
||
→ onStop() → 进入后台
|
||
→ WebSocket 保持连接
|
||
→ 推送/FCM 通知到达时,点击通知 → 恢复 MainActivity
|
||
```
|
||
|
||
## 4. 锁屏交互
|
||
|
||
### 4.1 锁屏唤醒
|
||
|
||
```
|
||
设备锁屏 + 息屏
|
||
│
|
||
├→ 说出唤醒词 "昔涟"
|
||
│ └→ onLaunchVoiceAssistFromKeyguard()
|
||
│ └→ 简化版覆盖层 (仅对话,无 IoT / 敏感操作)
|
||
│
|
||
└→ 长按电源键
|
||
└→ 同理
|
||
```
|
||
|
||
### 4.2 锁屏安全策略
|
||
|
||
| 操作 | 锁屏状态 | 行为 |
|
||
|------|---------|------|
|
||
| 查询天气/时间 | 允许 | 直接回复 |
|
||
| 简单闲聊 | 允许 | 直接回复 |
|
||
| IoT 查询(状态) | 允许 | 回复设备状态 |
|
||
| IoT 控制(开关) | **禁止** | 提示"请先解锁设备" |
|
||
| 查看记忆 | **禁止** | 提示"请先解锁设备" |
|
||
| 修改设置 | **禁止** | 提示"请先解锁设备" |
|
||
| 宿主命令 | **禁止** | 提示"请先解锁设备" |
|
||
|
||
## 5. 多窗口与分屏
|
||
|
||
- **分屏模式**:悬浮窗模式下不支持(本身已是覆盖层);全屏 Activity 支持分屏
|
||
- **画中画**:语音通话场景支持画中画(PIP),显示昔涟头像 + 波形动画
|
||
|
||
## 6. 手势交互
|
||
|
||
| 手势 | 悬浮窗模式 | 全屏 Activity |
|
||
|------|-----------|---------------|
|
||
| 下滑覆盖层 | 关闭悬浮窗 | — |
|
||
| 点击遮罩区域 | 关闭悬浮窗 | — |
|
||
| 长按消息 | 复制/分享菜单 | 复制/分享/删除 |
|
||
| 左滑消息 | — | 查看消息详情/时间戳 |
|
||
| 双击昔涟头像 | 切换输入模式(语音↔文字) | 同左 |
|