Files
matrix-screen-controller/移动端相关内容/安卓app/安卓开发详细设计.md
T

90 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Android 首版详细设计
## WiFi 加速扩展
App 0.3.0 / code 6。DeviceRpc 保留 BLE 分片与握手;WifiRpc 使用完整加密 WebSocket 记录;HybridRpc 串行业务路由并独立 BLE 保活,BLE 断开销毁两通道。MobilePlatform 可选 WifiPlatform 隔离 Android 网络 API;旧设备无 wifi_transport 能力则保持 BLE。AndroidWifi 监听非 VPN 的 WiFi Network,将 OkHttp SocketFactory 绑定该网络,不改变进程或系统默认网络,不要求互联网验证。
协议 1.2、一次性凭据及密钥布局见通信协议。平台网络事件撤销旧 Socket;按 2/5/10/30 秒重试;心跳与切网任务始终 BLE。后台立即停止预览,30 秒关闭全部连接。结果不明写入不重放,回读并提示。API 37 局域网权限拒绝保留 BLE,连接页提供设置入口。`usesCleartextTraffic` 允许本地 ws 握手,但业务和通道证明均应用层 AES-GCM 加密,不发送明文身份/业务/密钥。
本设计对应 MOBILE-* 和协议 1.0。已实现项以本文件说明及源码为准,真实通过范围见测试结果归档;测试目标不自动等于已完成验收。
## 1. 模块与依赖方向
工程使用 Kotlin DSL、Gradle Wrapper、版本目录和依赖校验;版本必须精确固定,不使用动态 latest。模块为 `androidApp`(Android 入口与平台组装)、`sharedCore`(KMP 协议/业务/状态机)、`sharedUi`(KMP Compose 界面);依赖 androidApp → sharedUi → sharedCore,androidApp 也实现 sharedCore 的平台接口。
应用 ID 固定 `org.qimiaoscreen.controller`,显示名称“奇妙小屏幕”,minSdk 26。首版 App 版本 `0.1.0`、versionCode 从 1 开始;交付构建增加 versionCode,不绑定设备 VERSION。debug 为当前唯一交付类型,无正式签名配置。平台工具链安装后将实际验证的 Kotlin、Compose、AGP、Gradle、JDK、SDK 版本登记在构建文档并提交锁定文件。
sharedCore 通过 MobilePlatform 聚合扫描、连接、手机型号、本地键值读写和 SecureChannel 工厂;DeviceLink 封装分片收发与关闭,SecureChannel 封装握手与加解密;Android BluetoothGatt、Activity、Context、Keystore 等类型不能出现在 commonMain。共享状态机使用协程与 StateFlow,取消结构化管理。JSON 使用 kotlinx.serialization,保留未知可选字段兼容策略。依赖注入显式通过构造函数完成,首版不引入额外 DI 框架。
Android 平台以 Java 安全 API 实现 P-256 ECDH/HKDF-SHA256/AES-GCM,公共模块定义字节契约;设备端使用成熟 Python 密码库。iOS 未来接入平台加密与 CoreBluetooth,不以 Android 类型模拟 iOS。
## 2. 状态机与异步行为
连接状态:PermissionRequired → BluetoothOff/Idle → Scanning → Connecting → Discovering → Subscribing → Handshaking → Ready;失败进入 Error(分类原因)并释放 GATT。主动断开清理订阅、密钥、分片、轮询和队列,但保留上次设备 ID。主动断开后当前前台会话不自动重连;用户再点连接或下一次进入前台才尝试。
扫描单轮 12 秒;点击重试开始新轮,不无限循环。自动重连扫描上次持久 ID 对应短编号,握手校验完整 ID,不因名称相同认错设备;候选完整 ID 不符则释放并报错,用户可重新扫描。App 最多一个 BluetoothGatt。每项 GATT 操作等待回调或超时后再执行下一项;迟到回调按连接 generation 丢弃。
用户控制队列优先,状态与当前帧次之,内容图片在空闲轮询时一次传一张。显示内容前台每 10 秒查询目录修订;全部可预览条目先传 16×16 PNG,第一轮尝试完成后再传 64×64 完整图。单个预览在途,数据无变化不反复下载。背景立即停止轮询和内容图片,30 秒延迟任务释放连接;回前台取消延迟,Ready 则刷新,非 Ready 则重连上次设备。进程死亡不假设回调可执行,由设备心跳门限回收会话。
普通操作请求超时 10 秒,扫描 WiFi 20 秒,切网任务最多轮询 60 秒后转“结果尚未确认,可重新读取”;超时不是事务回滚证据,不自动重发变更。
## 3. 页面行为
设备页:未连接时扫描列表与权限/蓝牙恢复入口;连接时身份、断开、昵称修改、版本及分组状态卡。所有未知状态用“暂不可用”及原因,不置零;容量读取有缓存。手机昵称只存本地,连接时加密发送。
内容页:顶部当前帧及更新时间,下方当前内容/动图控制,再下方设备顺序的库列表。演示、静态、动图可辨认,缩略图懒加载;条目按钮为“播放”和“设为开机默认并播放”。当前实际 Activity 测试使用 UI Automator 的控件语义文本定位,root 点击仅采用该节点实时位置;尚未完成独立 Compose testTag 测试矩阵。动画会话变化时取消旧滑动提交,不对新动画误发旧位置。
设置页:先设备设置,再 WiFi,再 App 本地设置。亮度滑动结束才提交;方向、刷新率和性能模式明确操作反馈。多个未保存字段组成 changes,带修订,冲突保留草稿并要求刷新后再提交。不要完整提交缓存 settings。
WiFi:扫描来自设备;允许手工 SSID;密码动作“保留/替换”,开放网络不要求密码。不提供已存密码读取。只在本次编辑内暂存密码,提交或离开时清除,不写 SavedStateHandle、日志和磁盘。静态 IPv4 必填地址、前缀、网关、DNS,DHCP 模式不提交残留静态字段。保存与连接结果分别显示。未支持的 EAP 类型明确禁用,不猜测配置。
所有页面适应小屏、字体放大和横竖屏;按钮提供无障碍语义。UI 采用共享 Material 3,跟随系统深浅色,无 WebView。图标采用代码/向量资源,首版无需图像生成依赖。
## 4. 平台权限与本地数据
连接异常清理:GATT 建立、加密握手和 RPC 的内部期限到期属于通信失败,必须转换为普通连接错误;不能把 TimeoutCancellationException 当成页面退出引发的协程取消而吞掉。期限到期关闭 GATT,清除会话并恢复扫描入口;变更命令不重放。仅在业务握手开始前,对同一设备的 GATT 建立最多尝试两次,间隔 1 秒;用户主动取消不重试。MTU 请求值为 247,应用报告的接收上限不超过此值;厂商重复 MTU 回调只能更新保守上限,服务发现与 CCCD 订阅只启动一次。
Android 8–11 按平台要求申请前台定位扫描权限并解释用途,系统位置开关影响扫描时提供设置入口;12+ 申请 BLUETOOTH_SCAN/CONNECT,并声明扫描不用于定位。不申请后台定位、联系人、文件全盘访问或摄像头权限。权限拒绝后允许重试,永久拒绝显示系统设置入口;不在启动时重复轰炸权限弹窗。
本地 SharedPreferences 保存连接记忆与手机昵称。内容目录及两档图片存于 Android 专属 cacheDir:设备 ID 目录隔离,图片按类型、条目 ID、修订和档位散列命名;目录原子写入,图片读取验证 PNG 尺寸,整体最多 128 MiB 并按最近使用时间淘汰。内存保留最多 128 张或 8 MiB Base64 字符,可见项按需从磁盘回填。目录修订未变才复用;变化后完整翻页并清理失效图,断线不显示旧列表。软件设置可清空该缓存,不清除设备记忆。当前设备画面沿用原有会话缓存,不写磁盘。设备业务配置以核桃派为准,不自动恢复手机历史副本。禁用敏感测试数据备份;密钥和 WiFi 密码不持久化。
## 5. 设备侧集成
Android GATT 时序补充:连接后请求 MTU 247;若厂商先报告缓存值 517,不立即开始服务发现。收到不大于请求值的实际 MTU 回调后,启动一次服务发现;缺少此回调时使用 2 秒后备任务启动一次发现。连接关闭取消后备任务。这样避免尚未完成 MTU 交换时提前发现服务导致停滞;整体仍受 15 秒 GATT 建立期限约束。此处理不更改协议线格式。
公共控制服务提供与协议对应的业务方法,网页 REST 与 BLE 适配器复用,禁止 BLE HTTP 回环调用网页接口。现有模板解析、默认事务、动画控制和设置应用由同一服务处理。配置修订比较与写入串行,网页操作也更新修订。
BlueZ D-Bus 接入作为可恢复模块,单独管理连接/广播,不在刷新线程执行 IO。蓝牙不可用时设备状态公开故障,显示与网页继续工作。持久身份不进入镜像载荷。网络扫描调用参数化 nmcli,解析转义 SSID,不拼接 shell;超时与错误脱敏。
网页顶栏从共享状态取得 mobile.connected/client_name;已连接状态首次加载只显示常驻标记,观察到会话变更时才显示短提示,断开更新状态。昵称通过 textContent 渲染,不插入 HTML。
## 6. 测试、部署与恢复
模拟 transport 使用同一协议/业务模型,不把 fake 直接混入生产扫描列表;仅调试测试入口选择模拟。测试包括 commonTest、Android instrumentation 与 Python 设备契约测试,共享黄金向量确保加密/分片互操作。真实 BLE 不由模拟测试替代。
部署沿用离线依赖、持久数据保护、真实 systemd 生命周期和失败恢复,启用蓝牙同步修改 dedicated_host 检查。本轮不改驱动扫描算法,不默认视觉验收;确需视觉检查先停下询问用户启动方式。手机端安装与设备端部署分别记录版本/结果,不把任一方成功等同整体成功。
## 7. 当前交互补充与验收边界
当前帧成功读取或 unchanged 回复均刷新本机确认时间;界面显示距最近成功确认的秒数,超过 6 秒提示可能过期,不把静态内容未变化当作断线。内容页读取 content.default.get 显示开机默认名称;设置默认后重新回读。
临时 WiFi 密码仅存在 Compose remember 中,可切换本次可见状态,点击提交后立即清空并隐藏;离开页面不保留。DHCP 提交空 DNS 列表,不带静态地址/前缀/网关。权限拒绝时显示原因和重试/应用设置入口,该分支仍需各 Android 版本实测。
状态详情当前采用可展开 JSON,包含服务、显示、网络、电源、性能和容量;尚未完成所有字段的中文分组卡片。不能用 Android 13 的已授权主机测试替代 Android 8–11 的定位开关/权限验证;模拟测试只在 commonTest 内,不随生产 APK 发布。
## 2026-09-26 四栏实现修订
采用稳定页面编号 0连接、1设备状态、2显示内容、3设备设置;保存设备完整 ID、昵称、短编号、最近连接时间,不保存 MAC。扫描状态与连接独立,旧回调按代数隔离;RSSI 由平台 DeviceLink 可选方法读取。顶部共用 WiFi 任务状态。菜单、折叠表单、确认弹窗使用共享 Compose;版本元数据从 Android BuildConfig 注入。非敏感 WiFi 草稿跨页保留,密码仅当前编辑驻留,离页或提交清除。原三页/JSON详情/刷新率与性能入口描述由此节替代。
## 2026-09-27 界面修订
共享状态增加仅当前认证会话有效的 connectedDevice 扫描快照,以本次句柄关联按钮,持久身份仍使用完整设备 ID。扫描重置保留它,重复广播按句柄去重;所有会话结束清空关联。顶栏使用共享 Compose 跑马灯,只在溢出时无限循环,文本变化重启。两处预览复用居中卡片,标题按刷新按钮实际宽度预留对称空间。App 0.2.1/versionCode 4,仅 debug。
## Android 选测入口
遵循 [按影响选测](如何安卓测试/按影响选测.md)。日常变更不自动执行模拟器或 root 真机全量矩阵;独立 uiTest 使用真实 Compose 界面与 Controller、测试专用假平台,不替代物理 BLE。历史版本专项不作为每轮门槛。
## 2026-10-10 动画浏览
动画读取使用协议1.3的帧信息与4 KiB分块接口,图片队列独立连续运行,每块结束让出命令锁。优先级:用户命令、状态/保活、全屏当前项、普通图库。普通队列先全部低清首图、再低清动画、最后高清。可见动画在后台解码并以单调时钟扣除解码耗时,保持源帧时长。全屏采用共享Compose Dialog、比例适配和1–8倍缩放;关闭300 ms撤销优先级,后台立即停新请求。动画清单、校验后的完整PNG和部分块纳入现有128 MiB缓存;完整高清缓存可直接恢复播放而无需重新请求低清。