# Cyrene-For-Android — Cyrene 安卓客户端设计文档(超详细讨论稿 v1) > 配套 Cyrene v2(git.yeij.top/AskaEth/Cyrene_v2)的 Android 客户端。 > **主人已确认的关键决策**(2026-09-08): > - 主界面 = **常规 AI APP 风格**(会话列表 + 聊天流)。 > - **长按电源键唤醒 = 全屏语音助手**(系统级语音助手交互),**不要悬浮球**。 > - UI **严格遵守 MIUIx / Miuix 设计风格**:官网 https://compose-miuix-ui.github.io/miuix/zh_CN/ ,组件库 https://compose-miuix-ui.github.io/miuix/zh_CN/components/ 。 > - **先做纯文本版本**(P0);语音(P1)后续。 > - 顶栏左上角**汉堡菜单**展开**侧边栏**,**预留 IoT 入口 + App 设置页入口**。 > - 后端契约详见 `Cyrene v2` 的 `Docs/api-reference.md` + `DevDocs/design/21-安卓app语音助手.md`(本文件为端侧细化)。 > 命名:仓库作者 `AskaEth`,日常名 `YeiJi / 叶酱`;App 名 `Cyrene`,角色 `昔涟`。 --- ## 0. 目录与工程形态 - **单 Module**:`app`(Kotlin + Jetpack Compose),Gradle 版本目录。 - 依赖:`compose-miuix-ui`(Miuix 组件)、`androidx.lifecycle.viewmodel-compose`、`Retrofit + OkHttp + kotlinx-serialization`、`okhttp`(WebSocket)、`EncryptedSharedPreferences`(JWT)、`hilt`(DI,可选)。 - `BuildConfig`:`BASE_URL`(默认可 `http://:8080`,release 换 HTTPS)。 - 包结构:`com.askaeth.cyrene.{app,core,data,domain,platform,ui}`(`app`=Activity/导航;`core`=Miuix 主题/Auth;`data`=Retrofit/WS/仓库;`domain`=会话/消息模型;`platform`=语音/权限/电源键;`ui`=各 Screen/组件)。 ## 1. 总体信息架构(功能分类) ``` Cyrene-For-Android ├─ A. 聊天(主界面,AI APP 风格) │ ├─ 会话列表:主会话「与昔涟」(web) + 次级会话(web:),可新建/删除/恢复 │ └─ 聊天页:气泡流(

多气泡、/ 旁白灰斜体仅chat、思维链/工具卡折叠、图片)、输入框+发送、语音按钮(P0占位) ├─ B. 侧边栏(汉堡抽屉) │ ├─ 会话/聊天 │ ├─ [预留] IoT(设备/场景)入口 │ ├─ [预留] App 设置入口 │ ├─ [可选] 记忆 / 子代理 / 自主思考(只读) │ └─ 关于 / 登出 ├─ C. 语音助手(长按电源键唤醒,P1)— 全屏,无悬浮球 │ ├─ 展开: 聆听动画 → 已识别文本 → 昔涟回复 → 再听/TTS │ └─ 系统级: AccessibilityService/系统语音助手回调 → 启动助手 Activity(全屏) ├─ D. [预留] IoT:设备/场景列表(占位) └─ E. [预留] App 设置:主题(Miuix 深/浅)、通知、语音偏好(ASR/TTS 端侧 vs 后端)、关于 ``` ## 2. 页面路由(单 Activity + 导航) - `LoginScreen`(首启无 token)→ `HomeScreen`(会话列表,含顶栏汉堡)→ `ChatScreen({sessionId})`(聊天) - `AssistantActivity`(P1 全屏语音助手,长按电源键拉起;无悬浮球,就一个全屏页) - `IotScreen` / `SettingsScreen`(占位页,P0 展示"规划中") ## 3. 数据层(对照现有契约,P0 纯文本即用) - **认证**:`POST /api/v1/auth/login {username,password}` → `{token,expiresAt,role}`(`role=owner`,单账号)。JWT `Authorization: Bearer`+`X-API-Version: 1`;`EncryptedSharedPreferences` 存 token;**REST 401 → `auth_expired` 清 token → 回登录**;WS 握手失败同理。 - **会话**:`GET /api/v1/sessions`(主会话 `id="web"` 恒在);`POST /api/v1/sessions` 建次级;`GET /sessions/{id}/messages?limit=50&before=&platform=`(**倒序热分页**,`platform=` 过滤);`DELETE /sessions/{id}`(主会话删=403)。 - **发消息**:`POST /api/v1/chat {sessionId,text,deviceId,stream?}`(`stream:true`→转 WS;忙时 `202 {queued,queueDepth}`、队满 `409 chat_busy`)。 - **WS** `/ws/chat?token=`:上行 `chat`/`interrupt`;下行 `message.start|delta|end`、`thinking.*`、`tool_call.*`、`message_persisted`、`history`(握手后首帧主会话最近 50 条)、`mood`、`session_busy`/`pending_*`/`session_idle`、`voice_output`(P1)。`message_persisted`/`history` 载荷为 `historyMessage`。 - **消息 DTO**:`{id,sessionId,role,content,mode?,mood?,image?,thinking?,platform?,deviceId?,senderName?,adapterId?,createdAt}`;`thinking` 仅 owner 可见;主流 `mode` 有 `chat`(含 `

`/`/` 需端侧解析)。 - **deviceId**:`voiceassist:myapp:v1`(design/16 §4.5 允许自定可读前缀),`POST /chat`/ws `chat` 携带 → 落库标注来源;主会话 `web` 与 Web 共享上下文(multiplatform 同步)。 ## 4. 消息渲染(聊天页核心) - 按 `mode` 决定形态:`chat` 用气泡;其它 `mode`(backthink/工具/审计等 refs)卡片化或折叠。 - **`chat` 文本解析**:把 content 按 **`

`** 拆成多条气泡(每段一条);`…`/`…` 解析为**灰斜体小字旁白**(依附气泡,不独立成气泡);`*…*`/`*…*` 兼容。**非 chat 消息不解析**这些标签。 - `thinking`(仅 owner):可折叠「思维链」面板;`tool_call` →「工具卡」(折叠,可看参数/结果)。 - 流式:`message.delta` 追加到当前气泡末尾 + 光标;`message.end` 收口。 - 图片:`image`(base64 data: URI 或 URL)→ Coil 加载。 ## 5. 语音助手(P1,长按电源键 全屏,无悬浮球)— 端侧与后端协同 - **触发**:① 系统级语音助手回调(`VOICE_INTERACTION` / `AssistantService`)或 ② `AccessibilityService` 监听 `KEYCODE_POWER` **长按**(Android 对电源键长按有限制,需在系统「电源键双击/长按」设置里把本 App 设为语音助手,或通过系统辅助「voice assistant」入口)。落地:**声明 `VOICE_INTERACTION_SERVICE`**,长按电源键由系统拉起本 App 的 `AssistantActivity`(全屏)。 - **链路**:`AssistantActivity` 聆听(`MediaRecorder`/`AudioRecord`)→ 录音交给 **ASR**(**端侧 or 后端**,见开放问题;后端当前 ASR/TTS 是占位,需先补 design/21 后端补强或端侧 whisper)→ 出文本 → `POST /api/v1/chat {text,deviceId}`(或 WS 流式)→ 昔涟回复 → **TTS** 合成朗读(端侧 e.g. `TextToSpeech` 或后端)。全程单页无悬浮球。 - **保活/后台**:可选前台服务(语音持续/推送),权限最小化;无需悬浮球全局浮层。 ## 6. MIUIx / Miuix 映射(紧跟 compose-miuix-ui) - 用 `compose-miuix-ui` 的 `MiuixTheme` + 组件:`TopAppBar`(汉堡/标题)、`Scaffold`/`Drawer`(侧边栏)、气泡用 `BubbleView`/卡片、`TextField`(输入)、`Button`(发送)、`Switch`/`List`(设置)、`Snackbar`/`Dialog`。**禁用原生 Material 组件**,全 Miuix 风格(圆角、毛玻璃、液态玻璃、强调色)。 - 顶栏左上汉堡 → 侧边栏(`Drawer`);侧边栏含「IoT」「App 设置」占位入口(P0 点开显示"规划中")。 ## 7. P0(纯文本)MVP 任务清单 1. 工程搭建:Gradle + Compose + Miuix 依赖 + `BuildConfig.BASE_URL` + Hilt(可选)。 2. `core`:Miuix 主题、AuthManager(EncryptedPrefs 存 JWT、401→auth_expired→登出)。 3. `data`:Retrofit(login/sessions/messages/chat)、WS `ChatSocket`(`/ws/chat?token=`,事件分发到 StateFlow)、`ApiClient`(`Authorization: Bearer`+`X-API-Version`)。 4. `domain`:`Conference`/`ChatMessage` 模型、`HistoryMessage` 映射、`

`/`/` 解析器。 5. `ui`:`LoginScreen` → `HomeScreen`(会话列表)→ `ChatScreen`(气泡流 + 流式 + 思维链/工具卡 + 输入框)。顶栏汉堡侧边栏(IoT/设置/登出)。 6. 设备标识:`deviceId=voiceassist:myapp:v1`。 7. 验证:登录 → 拉主会话历史 → 发消息 → WS 流式收到回复 → 跨端(web/微信)同步显示。 ## 8. 长线 roadmap - **P0(纯文本)**:⑦ 完成 → 可日常聊天,多端同步。 - **P1(语音助手)**:后端补 ASR/TTS(design/21)→ 电源键长按唤起全屏助手 → 聆听/ASR/chat/TTS 朗读闭环 → 无悬浮球。 - **P2(智能)**:IoT 入口真实现(设备/场景)、App 设置功能化(主题/通知/语音偏好)、主动推送 + 系统通知、多角色(persona)切换、记忆/子代理/自主思考只读面板、多会话管理增强。 ## 9. 开放问题(待与主人讨论 / 后续敲定) 1. **[已定案] 长按电源键**:设置 App 为**系统默认语音助手**(`VOICE_INTERACTION_SERVICE` / `AssistantService`),由系统在长按电源键(或系统语音助手入口)时拉起本 App 的 `AssistantActivity`(全屏),无悬浮球。厂商(MIUI)自家更顺,需在系统「语音助手 / 电源键」设置里把本 App 设为默认。 2. **[已定案] ASR/TTS 后端化**:**不在端侧**——因第三方适配器(微信 / KOOK 等 IM 渠道语音)**无法在端侧实现**,且为大后期**语音 / 视频通话**打基础。语音闭环统一走后端真实 ASR / TTS。**依赖**:后端 `voice` 链路当前是降级占位(cloud endpoint 空 → 降级、silent 空音频),需先接通真实 ASR / TTS(本会话 TTS/ASR 进程在做)。Android 语音 P1 依赖这项完成后接入。 3. **Miuix 组件精确映射**:到 `components` 页逐组件对照,列出"我们用哪个"。 4. **多角色**:现在登录恒 owner,暂无双角色切换;`GET /personas` 可只读展示人格列表。 5. **会话管理 UI**:次级会话的新建/切换/删除入口。 6. **Hilt vs 手写 DI**:视复杂度定。 ## 10. 红线(必须遵守) - JWT 存储加密(EncryptedPrefs),不落明文/不打日志;401 即登出。 - 身份靠 actor 元数据 + owner.yaml 白名单(登录即 owner),不靠提示词。 - 语音/音频:权限最小化、显式授权;**不做悬浮球全局浮层**。 - 严格 Miuix,禁原生 Material;`Docs/api-reference.md` 契约随实现更新。