deviceId 持久化与排障

多设备游标的前提是“同一安装稳定、跨安装不同”的 deviceId。它由各端 SDK 内部生成与持久化,不是新的公开 API(IMLib 仍 102 个语义 op,契约无 deviceId 操作);业务无需传参。本页列出各端实现、重置方式与排障。

各端实现​

端生成持久化位置说明
Web`crypto.randomUUID()`(不可用时随机十六进制)localStorage["imkit:deviceId"]同 origin 共享;隐私模式/只读存储降级为内存值
Electron`randomUUID()`<dbPath>/im-electron/device.json(含 deviceId/createdAt)主进程持有;与硬件无关
Android`android-<32hex>`ImStore KV:rev25.device_id超长/空白视为损坏并重生成
Flutter`flutter-<32hex>`DeviceIdStorage:device_id:<appkey>按 appkey 隔离;读写失败不阻断建连

四端共同规则:trim 后 ≤128 字符;断线重连/重新 init 复用;disconnect() 不清除;只有清缓存/卸载/换设备才会生成新值。

公开 API 边界​

项结论
IMLib 契约无新增 op:仍是 102 个语义 op;无 getDeviceId/setDeviceId 契约方法
业务传参不需要传 deviceId;SDK 自动生成并追加到 WS query
Electron 诊断辅助主进程客户端/工厂额外提供只读 getDeviceId()(排障用,不属于契约 API)
Web/Android/Flutter不对外暴露 getter;排障看本地存储键
服务端只把 deviceId 当游标维度;不提供设备列表/下线接口

何时会变化​

  • 清除浏览器站点数据 / 换浏览器 profile / 无痕窗口(Web 每次新会话都可能新 deviceId)。
  • 卸载重装、清除应用数据、迁移到新设备(Android/Flutter/Electron)。
  • 本地存储损坏/超长(>128)被 SDK 重新生成。
  • Electron 更换 dbPath(数据库目录迁移会被视为新设备)。
变化的影响

deviceId 变化 = 新设备:游标从 0 开始,首次连接会补收全部未 ack 消息(每会话 ≤500 条)。这不是消息重复,而是新设备缺少确认记录。

排障​

现象排查处理
每次启动都收到全量补收检查本地存储键是否存在/被清保留站点数据/应用数据;Electron 确认 dbPath 稳定
握手 400(deviceId 超长)自定义连接是否手工传了超长值交给 SDK 生成;或截断到 ≤128
hello.deviceId 与服务端日志不一致SDK 回显校验告警确认 SDK/服务端均为 rev25;不一致不影响连接但游标可能错位
同一账号两端共享游标两端是否复制了同一存储(镜像/克隆 profile)确保每安装独立存储;不要手工指定 deviceId
多端未读不同步未读是用户级(已知限制)以会话列表/未读接口为准,不要期望端级未读
Web 无痕模式每次都补收localStorage 不持久预期行为;提示用户或改用普通窗口

相关链接​