Seetong · Report
🎯 Seetong 问题雷达 第258期
时间窗口:2026-10-26 17:00:00~2026-10-27 17:00:00
TL;DR 核心要点
- 🔴 iOS 8.4.1.6 长连接一夜重建 37 次、每 6 分钟切一次接入节点,报警推送与设备在线态因此丢包(严重度 76,置信度 中)
- 🟠 iOS 8.4.1.6 报警页首次进入要卡十几秒,通知权限查询与列表重建都在主线程上(严重度 68,置信度 中)
- 反馈 259780:2026-10-26 23:48:36,iOS 8.4.1.6,iPhone 26.6,山东(账号尾号 4123),原文“报警很卡”,随附 Logan(8 129 行,覆盖 2026-10-26 00:16~23:47)。
最近一个月 Top 问题
按严重度与复发期数排序,已把跨期同类反馈归集;负责人由问题代码锚点对应的 Git 提交历史(blame / 近期主要提交者)反查;数据窗口:最近 30 天(截至 2026-10-27)。
| # | 问题(严重度降序) | 严重度 | 平台 | 版本 | 负责人 | 问题原因 |
|---|---|---|---|---|---|---|
| 1 | HarmonyOS `1.1.2.3` 多用户离线与核心视频链路失效 20 期 · 170 条反馈 | 100 | Android · HarmonyOS | 1.1.1.11 / 8.4.1.6 / 1.1.2.3 | 陈宝旺、唐胜、冉博麟、谭伟 | HarmonyOS 客户端把 P2P 瞬时离线写成本地持久状态,并在后续在线判断中优先使用这个旧值,可能导致设备已恢复在线却仍显示离线;回放离线态和播放错误透传不足则放大了用户的“看不到画面”体验。 |
| 2 | Android `8.4.1.6` HEVC 预览以零宽高启动解码器 1 期 · 3 条反馈 | 90 | Android | 8.4.1.6 | 张威、唐胜、谭伟 | Android 8.4.1.6 在首次 TPS_AddWachtRsp 尚未提供有效 HEVC 宽高时,仍立即调用 OpenStreamAgent 创建 MediaCodec,系统以 BAD_VALUE 拒绝零宽高配置,而客户端没有等待后续媒体参数或建立明确失败终态。 |
| 3 | Android 与 iOS 8.4.1.6 报警功能突然失效与通知不达 1 期 · 3 条反馈 | 90 | Android · iOS | 8.4.1.6 | 唐胜、许源 | 现有客户端样本表明 Android 通知权限与 token 注册均成功,故障更接近“服务端未生成报警或推送任务未送达”,但神策缺少报警生成与推送到达事件,iOS 样本又混合了通知权限关闭,当前不能完成单点定因。 |
| 4 | HarmonyOS 画中画状态导致切换设备后仍显示前一路画面 1 期 · 3 条反馈 | 90 | HarmonyOS | 1.1.1.11 / 1.1.2.3 | 张跃译 | 多个 HarmonyOS 画面共享一个无代次、无串行化、无旧控制器清理的 PipManager,切换设备时旧创建任务和新选择竞争,最终把第一路 XComponent、savId 或恢复状态保留下来。 |
| 5 | 升级后回放体验整体退化 5 期 · 20 条反馈 | 85 | Android · HarmonyOS · iOS | 8.4.1.6 / 1.1.2.3 / 8.3.14.2 | 唐胜、许源、欧阳荣、谭伟 | 8.4.1.6 对回放链路做了多处改动(时间条 UI、通道切换进度对齐、报警-录像联动),导致回放体验多点退化;Logan 显示取流层无崩溃,问题在"UI/状态对齐 + 报警录像关联"而非连接失败。 |
| 6 | KMP 回放页未申请屏幕常亮,回放中手机自动息屏 11 期 · 27 条反馈 | 84 | Android · HarmonyOS | 8.4.1.6 / 8.4.1 / 8.4.2 | 唐胜、陈宝旺、谭伟、许源 | KMP 回放页的屏幕常亮能力已在代码中完整实现(KMP 公共层 → 桥接层 → Android 宿主层齐备),但承载该实现的提交只落在 feature_v8.4.2 一条分支上,feature_v8.4.4、master、hotfix_v1.1.1 全部不含,因此所有已发布版本(Android 8.4.1.6 / HarmonyOS 1.1.1.11)在运行时都走不到 FLAG_KEEP_SCREEN_ON,回放过程中发生系统级息屏。 |
| 7 | Android 实时预览无首帧却被标记为“视频播放中”,并无限重试 7 期 · 22 条反馈 | 80 | Android · iOS | 8.4.1.6 / 1.1.2.3 / 8.1.1.11 | 唐胜、陈宝旺、欧阳荣、谭伟 | 预览页把“取流请求已提交”或“设备在线状态消息”误当成播放成功,而没有把首帧到达作为唯一成功门禁;add_watch_result=-1 后仍持续 10 秒重试并显示“视频播放中”,导致用户长时间等待且无法获得明确失败反馈。 |
| 8 | SD 卡跌至不可读写或反复未初始化,录像回放被直接阻断 3 期 · 9 条反馈 | 80 | Android · HarmonyOS · iOS | 8.4.1.6 / 1.1.1.11 | 唐胜、张威、陈宝旺 | 设备上报的 SD 卡状态在 258245 中持续处于未初始化/格式化中,在 258173 中由正常可读写跌至不可读写;App 按协议正确展示异常,根因更可能在 SD 卡、卡槽/供电、设备存储控制器或固件挂载逻辑,而不是 KMP 页面误报。 |
| 9 | iOS `8.4.1.6` 云回放卡顿,首帧与失败状态可能被提前结算 2 期 · 8 条反馈 | 80 | Android · iOS | 8.4.1.6 / 8.3.11.3 / 8.4.106 | 陈宝旺、欧阳荣、谭伟 | iOS 云回放容器允许解析完成后在 1.2 秒无首帧时提前向 KMP 返回成功,同时把 IJK 播放错误与正常结束合并处理,导致页面对真实卡顿、缓冲超时或解码失败缺少准确状态和可回溯证据;这是高度可疑的共同客户端缺陷,但仍需复现确认其是否为 3 名用户的直接主因。 |
| 10 | iOS 8.1.2.4 微信登录授权码重复提交触发 30100225 1 期 · 3 条反馈 | 80 | iOS | 8.1.2.4 / 8.1.204 / 8.4.106 | 待定 | 微信回调与恢复登录没有一次性 state、幂等锁和授权码消费机制,重复回跳或重试会把同一个单次授权码再次发给服务端,服务端以 30100225 拒绝后客户端仍保留旧状态。 |
🔴 问题 1:iOS 8.4.1.6 长连接反复重建,报警推送与设备在线态被拖垮 | 负责人:欧阳荣、位冬、唐胜、许源
1. 现象与覆盖范围
- 反馈
259780:2026-10-26 23:48:36,iOS8.4.1.6,iPhone 26.6,山东(账号尾号 4123),原文“报警很卡”,随附 Logan(8 129 行,覆盖 2026-10-26 00:16~23:47)。 - 该用户在近 24 小时内共提交 2 条同族反馈:
259780(“报警很卡”)与259617(2026-10-26 00:38,“报警信息经常短缺”)。两条出自同一账号、同一机型,指向的是同一件事的两个侧面——列表卡,以及消息本身不全。 - 同期还有 iOS
8.4.1.6的两条卡顿反馈:259896(2026-10-27 16:28,iPhone 17.5.1,广东,“更新后 APP 出现严重卡顿现象,卡回放无法播放,进入 APP 后卡顿得无法操作,偶尔还会闪退出”)、259911(2026-10-27 17:38,iPhone 26.3,江苏连云港,“卡顿”)。两条都带 Logan。 - 另有
259824(2026-10-27 10:47,iPhone 27.0,内蒙古,“下面栏里,报警那里一进去就特别卡”),其症状更接近本期问题 2,单独在第 2 节展开。 - 严重度评分:76 / 100。反馈量 20(本窗口 4 条直接反馈、3 条带 Logan,其中 1 名用户在 23 小时内重复提交);共性广度 30(iOS 单一端,但覆盖
8.4.1.6一个版本、iPhone 17.5.1/17.6.1/26.3/26.6/27.0 五个 iOS 版本、山东/广东/江苏/内蒙古四个省级地区);业务关键度 30(报警推送与设备在线态,是消息主链路;未达设备掉线的 40 分档)。 - 与第 257 期(今日 09:00)的关系:09:00 那期的窗口是 2026-10-26 17:00:54~2026-10-27 09:00,
259780与259617都落在该窗口内,当期把它归入「app 卡死 / 报警很卡 🟡 单点」而未展开。本期拿到了同账号的 8 129 行完整日志,把「卡」拆成了可验证的长连接重建问题,因此不属于重复占用,而是对同一现象补上了此前缺失的证据。
2. 神策证据
- 事件总量基线(2026-10-27 截至查询时):
DeviceConnectResult16 201 468 次/5 285 091 人MonitorFrameResult39 603 822 次DeviceVideoPlayback15 557 262 次SiotDevConnectResult3 709 046 次AppSwitchStatusValue3 137 335 次- 参考上一条:
DeviceConnectResult是客户端主动发起的设备连接频次事件,量级远大于SiotDevConnectResult(后者每设备仅埋一次)。长连接反复重建会连带触发设备状态重新拉取与连接重试,因此这两个事件的比值可以作为「客户端侧连接动作是否异常放大」的旁证,但不能单独证明长连接重建。 - 口径限制(必须说明):当前事件清单中不存在长连接建立、断开、心跳超时或接入节点切换的专用事件。
Login(2026-10-27 为 565 980 次)只覆盖账号登录,不覆盖 ws 会话;AppSwitchStatusValue只反映前后台切换。因此神策只能提供「消息与连接规模」的背景,无法量化 ws 重建次数,本问题的量化证据全部来自 Logan。 - 已核对 2026-10-27 全量事件名清单(前 30 个),确认
AlarmMessage、WsManager等历史文档中出现的事件名在当前环境中不存在,本期不使用这些事件做任何推断。
3. Logan 关键日志
反馈 259780,Logan 8 129 行,覆盖 2026-10-26 00:16:24~23:47:38,运行环境 st_run_env_pro,version: 8.4.1.6,clientId: 913386C3-3847-403F-B7DA-CC55125A658D。
- 冷启动次数:
初始化SDK日志信息共出现 6 次(00:16:24、02:20:43、09:12:00、11:02:13、18:54:45、23:47:38)。间隔分别为 124.3、411.3、110.2、472.5、292.9 分钟,属于用户主动杀进程重启的形态,不是系统连续崩溃重启。 - 长连接重建次数:
开始初始化长连接共出现 37 次。也就是说,除了这 6 次冷启动,还有 31 次是在 App 存活期间重建的 ws 会话。 - 接入节点反复轮换:37 次初始化命中的 ws 地址至少包括
122.9.8.100、114.116.213.86、114.116.196.16、114.116.220.7、122.9.40.201、122.9.45.119、114.116.196.211、114.116.222.246、122.9.14.70等 9 个不同节点。每次重连都重新走/seetong-netty-manager/netty/manager/get/available/netty/server重新分配节点,说明客户端没有做节点粘滞。 - 60 秒内再次重建:5 次。
09:52:57→09:53:45(47.8 秒)、15:26:26→15:27:18(52.0 秒)、17:33:38→17:34:37(59.6 秒)、17:48:28→17:49:06(38.8 秒)、23:46:44→23:47:38(54.1 秒)。另有多次 2~5 分钟量级的重建(15:27:18→15:29:07109 秒、15:29:07→15:33:23257 秒、16:24:35→16:28:36241 秒)。合起来看,15:21~17:49两个半小时内重建 12 次,平均 12 分钟一次。 - 断开的形态:
主动断开长连接日志信息 - code: 1001 - reason: Stream end encountered反复出现,日志里记为「主动断开」,即客户端侧调用关闭,而不是服务端 1011/1006 之类的异常掉线。 - 重连标志恒为 1:
websocketUploadLoginInfo里reconn取值来自self.reconnection,而self.reconnection在首次登录成功后即被置为YES(WebSocketManager.m:562),在RMWebSocketClose(:378-403)与didClose路径中都没有复位,只在:762一处出现self.reconnection = NO。反馈日志对应的会话在重建后仍以reconn=1上报,与「客户端把每一次重连都当成首次重连」的形态一致。 - 心跳与重建的关系:
initHeartBeat(WebSocketManager.m:249-259)先判heartBeatTimer是否存在,若不存在则先调destoryHeartBeat再dispatch_async到主线程创建 10 秒周期定时器;destoryHeartBeat(:378-389)本身也是dispatch_async(main_queue)里invalidate+ 置 nil。两个异步块都在主队列,顺序上destory的 block 可能排在新initHeartBeat之后执行,把刚建的 timer 置成 nil。反馈日志中每一次长连接连接成功后都没有稳定的 10 秒心跳节奏(日志只记录--- 取消心跳 destoryHeartBeat ---,没有对应的 senderheartBeat 记录),与「心跳被自己取消」的推演一致,但当前 Logan 未打印 senderheartBeat 内容,此点尚未闭环。 - 对业务的影响面:用户因「报警很卡」「报警信息经常短缺」两次提反馈,而报警列表的实时增量依赖 ws 推送(
kSocketGetDeviceAlarmList走WebSocketManager)。每次重建都会形成 1~5 秒的空窗,叠加getNetty的节点重新分配,足以让这段时间内的报警推送丢失或延迟,随后由下一次全量拉取补齐——这正是「消息短缺」与「进来就卡(触发重拉)」的典型形态。 - 反馈
259896的 Logan(3 922 行,覆盖 10:00:22~16:27:04)同样在 15:13:39 出现一次完整的 SDK 重新初始化,说明长连接重建不是单账号孤例。
4. 代码定位
- 涉及模块:
Seetong-App-iOS/Seetong5.0_ios/Seetong_tps/Tools/Scoket/WebSocketManager.m(iOS 长连接管理,当前分支feature_v8.4.2)。 - 关键类与文件:
WebSocketManager(WebSocketManager.m,属性heartBeatTimer在:35、reconnection在:42)。 - 心跳生命周期调用链:
connect(:60、:130)→initHeartBeat(:249)→destoryHeartBeat(:378)→[timer invalidate]。 - 关键分支:
initHeartBeat第 251 行的if(self.heartBeatTimer) { return; }与紧随其后的[self destoryHeartBeat]相互矛盾——既然已经确认 timer 为空,紧接着的销毁就是把「待创建的 timer」置于异步销毁风险中。 - 重连链路:
reConnectServer(:310起)→performReconnect(:333)→[WebSocketManager getNetty]。 - 关键分支:
reConnectServer只在readyState == SR_OPEN || SR_CONNECTING时提前返回;reConnectCount >= 5时停止重连。反馈日志中重建次数远超 5,说明有某个路径在每次连接成功后重置了计数,或绕过了reConnectServer直接走getNetty。 - 重连标志:
websocketUploadLoginInfo(:545-563)读self.reconnection;self.reconnection = YES在:562;self.reconnection = NO仅出现在:762。RMWebSocketClose(:378段)未复位该标志。 - 关闭路径:
RMWebSocketClose(WebSocketManager.m:389-407)→[self.webSocket close]+_webSocket = nil+destoryHeartBeat+destoryNetWorkStartTesting,同时把isAppStartWakeup置 NO。 - 修复方向锚点(按优先级):
WebSocketManager.m:249-259:把initHeartBeat的「判空 → 销毁 → 异步创建」改为同一次主队列同步执行,或去掉判空后的destoryHeartBeat调用,消除「异步销毁覆盖新建」的竞态。WebSocketManager.m:389-407/:762:在RMWebSocketClose与didClose中统一把reConnectCount复位,并让reconnection只在首次登录成功时置 YES、在每次断开时置 NO。getNetty调用点:增加 ws 会话单飞——同一clientId在connecting或open状态下拒绝再次发起getNetty,并打点记录调用方。- 接入节点:在
getNetty返回的节点可用时优先复用上一次节点,避免每次重建都切换。
5. 根因结论
- 置信度:🟡 中。
- 一句话根因:iOS 长连接的心跳与关闭路径存在「异步销毁覆盖新建定时器」与「重连计数/重连标志不复位」两处状态机缺陷,使连接在无服务端主动断开的情况下被客户端反复重建,每次重建都形成推送空窗。
- 关键证据链:
- Logan 侧:37 次 ws 重建 vs 6 次冷启动(31 次非用户触发);5 次在 60 秒内重建;断开 reason 恒为
Stream end encountered(客户端侧发起);9 个接入节点轮换。 - 代码侧:
initHeartBeat判空后仍调用destoryHeartBeat,两者均dispatch_async(main_queue);RMWebSocketClose复位了isAppWakeup但未复位reConnectCount/reconnection。 - 用户侧:同账号 23 小时内两次提交「报警很卡」「报警信息经常短缺」。
- 未闭环处:本期没有拿到
senderheartBeat的实际发送记录,也没有服务端侧的 ws 会话时长统计,因此「心跳被取消」这一环仍是推演,不是实测。
6. 建议下一步
- 分配给:iOS 基础组件负责人(长连接 /
WebSocketManager),由欧阳荣跟进复核。 - 优先处理项:
- 在
initHeartBeat、destoryHeartBeat、RMWebSocketClose、websocketDidOpen、websocketUploadLoginInfo五处补打reConnectCount、reconnection、heartBeatTimer是否为空、以及调用方堆栈,一次灰度即可判断是「谁在 open 后立即关」。 - 修掉
initHeartBeat的异步销毁时序问题,把reConnectCount/reconnection的复位下沉到RMWebSocketClose与didClose。
- 验证方法:
- 真机(iPhone 26.x、27.0 各一台)后台驻留 2 小时,统计
开始初始化长连接次数应 ≤ 冷启动次数 + 3;reconn在重建首次之后应为 1 且不入库为新会话。 - 报警推送回归:服务端在 ws 重建窗口内下发报警,验证 30 次下发无丢失。
- 心跳:抓包确认 10 秒周期心跳持续存在,且
destoryHeartBeat与新initHeartBeat不交叉。 - 任务账本:沿用
T-20261027-171012-c2c8(P1,captured),本期已更新其next_action补入259780的 37 次重建与节点轮换证据。
🟠 问题 2:iOS 8.4.1.6 报警页首次进入卡十几秒,主线程同时扛权限查询与列表重建 | 负责人:欧阳荣、Not Committed Yet、谭伟、唐胜
1. 现象与覆盖范围
- 反馈
259824:2026-10-27 10:47:48,iOS8.4.1.6,iPhone 27.0,内蒙古(账号W_LP84UmIedZ),原文“下面栏里,报警那里一进去就特别卡”,随附 Logan(3 178 行,覆盖 08:17:05~10:47 前后)。 - 同族旁证:
259780(“报警很卡”)、259769(2026-10-26 22:21,iOS8.4.1.6,iPhone 18.6.2,安徽,“经常 app 卡死”)、259896(“进入 APP 后卡顿得无法操作,偶尔还会闪退出”)。 - 严重度评分:68 / 100。反馈量 20(4 条直接反馈、3 条带 Logan、跨越 4 个 iOS 系统版本);共性广度 30(iOS 单端,覆盖
8.4.1.6与 17.5.1/18.6.2/26.3/26.6/27.0 五个系统版本、安徽/广东/江苏/内蒙古四个省级地区、4 个不同机型);业务关键度 25(报警入口可用性,属关键交互但非完全不可用)。 - 与上一条的关系:长连接重建(问题 1)会让报警页每次进入都触发一次全量重拉,是「卡」的放大器;本条关注的是页面自身的首屏路径——即使连接正常,首次进入也存在主线程阻塞。
2. 神策证据
- 神策侧没有报警页首屏耗时、主线程卡顿或页面渲染耗时的埋点。已核对 2026-10-27 事件清单:与页面相关的只有
$AppViewScreen(404 407 284 次)、$AppClick(266 940 102 次)、$pageview(940 665 次),均无耗时字段。 - 唯一可用的规模参照:
AppSwitchStatusValue2026-10-27 为 3 137 335 次/648 590 人,其中8.4.1.6占 2 139 162 次;用户在这台 iPhone 26.6 上单日 37 次 ws 重建、6 次冷启动,说明前后台切换频繁。每次回前台都会触发 KMP 报警页的pageDidAppear刷新路径(见第 4 节),这是「一进去就卡」的触发条件之一。 - 结论口径:神策在本问题中只能做背景,不能做量化,主证据来自 Logan 与代码。
3. Logan 关键日志
反馈 259824,Logan 3 178 行,覆盖 2026-10-27 08:17:05 起,os: ios、version: 8.4.1.6、clientId: 66CD0A06-F637-4C6C-A023-45907A542755,type: 27.0。
- 08:17:05.434
当前APP使用的语言: 中文 (中国),08:17:05.584初始化SDK日志信息 … version: 8.4.1.6,08:17:05.665获取到设备列表后,唤醒低功耗设备日志信息 - 低功耗设备数量: 0 - 是否为工程商: 0 - 长连接状态: 0。这是冷启动后进入首屏的完整序列。 - 日志首行
2026-10-27 08:17:05.441 EXCEPTION 1 --- [clogan] clogan header,说明该份日志的头部被截断,08:17 之前的内容没有采集到。因此本期无法从该条反馈直接看到报警页的进入时刻与卡顿时长,只能拿到条目提交(10:47:48)前的会话片段。 - 上一条反馈
259780中同类页面的日志显示,报警页的数据来源是 ws 接口kSocketGetDeviceAlarmList,并伴随/seetong-member-device/device/list、/seetong-member-device/device/group/list、/seetong-sms/member-message/unread/count、/seetong-mall/device/va_service等 20 个接口在页面进入后集中请求(该份日志中device/list与device/group/list各被请求 46 次)。 - 反馈
259780中同一账号在 23:48:36 提交「报警很卡」,其日志末段 23:47:38 的初始化SDK之后紧接 ws 重建,说明用户是在重启 App 后立刻进入报警页并感知到卡顿。 - 客观限制:本期两份 iOS 报警页 Logan 都没有打印主线程耗时、页面生命周期耗时或 UI 卡顿日志(
AlarmMsgViewController只打NSLog业务流水,KMP 侧AlarmMessagePage只打LogUtils.i状态串)。因此「卡了多久」目前只能由用户描述给出,无法从日志侧量化。
4. 代码定位
- iOS 原生侧(报警页宿主):
Seetong-App-iOS/Seetong5.0_ios/Seetong_tps/Classes/TPS/UIVC/VCMessage/AlarmMsgViewController.m(2 011 行)viewWillAppear:(:138-151)在每次进入时同步执行getDeviceIds、getDeviceUids,设备为 0 直接updateNoDataView,否则startRefreshTableHeader→loadData(:432)。checkNotification(:786-806)调用[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:],回调内dispatch_async(main_queue)再更新提示条。权限查询本身在系统进程侧,首次NotDetermined时会弹出授权对话,是首屏主线程可感知停顿的候选来源。refreshLatestAlarmListDataIsRefresh:(:596-651)先queryAlarmTimelineFromDBWithDate:(STAlarmTimelineCacheTool.m:37-60,FMDatabaseQueue inDatabase内SELECT * FROM alarmtimeline where user_id=? AND alarm_date=? ORDER BY last_timestamp全量读当天时间轴),回调里再queryAlarmDataFromDBWithDate:全量读当天报警,两段 DB 读取都发生在回调链上。removeDuplicatesFromDeviceAlarmList:usingMessageModeArray:(:1844-1876)对每条新报警在messageModeArray上做一次indexOfObjectPassingTest,复杂度 O(n×m)。这段在:1832的for (NSInteger i = 0; i < 15; i++)日期循环内被反复调用,报警条数越多退化越明显。- KMP 侧(Android / HarmonyOS 共用,iOS 也走同名页面):
seetong-kmp/moduleMessage/src/commonMain/kotlin/com/seetong/modulemessage/page/AlarmMessagePage.kt(2 540 行,分支feature_v8.4.2)pageDidAppear(:320-341):非首次加载时依次refreshDeviceOptions(reason = "page_did_appear")、resumeHeaderRefreshIndicatorIfNeeded()、refreshAlarmHistoryAfterPageAppears(reason = "page_did_appear")、syncPendingOnlineAlarmMessages(trigger = "page_did_appear")。observeForegroundEvent(:826-838):EVENT_APP_FOREGROUND时同样执行上述四步,reason 换成app_foreground。refreshAlarmHistoryAfterPageAppears(:977-1018):仅对 iOS 生效(if (!pagerData.isIOS ...) return),置isRefreshing = true后lifecycleScope.launch调vm.refreshHistoryAfterPageAppear。AlarmMessagePageViewModel.refreshCurrentHistoryUiState(:857-914):resetPaging→loadedDateKeys.clear()→loadedTimelineWindows.clear()→primeLatestTimelineWindowFromCache→syncLoadedMessagesFromCache→rebuildFilterOptions→buildSuccessUiState→requestFirstPage(forceRemote = true)。也就是说每次回前台都要重建整个列表状态并强制远程重拉第一页。- 修复方向锚点:
AlarmMsgViewController.m:786:把首次通知权限「询问」从页面加载路径剥离,页面只读getNotificationSettingsWithCompletionHandler结果,授权询问改到启动后空闲或用户主动触发;并对该调用加耗时日志。AlarmMsgViewController.m:1844:把msgId去重改成用NSDictionary/NSMutableSet建索引,把 O(n×m) 降到 O(n+m)。AlarmMessagePage.kt:826-838:回前台刷新加节流(例如距上次成功刷新 < 30 秒直接跳过),避免 ws 反复重建时每次回前台都触发一次全量重拉。AlarmMessagePageViewModel.kt:899:requestFirstPage改为可取消 + 首屏优先,先用缓存cachedState上屏,远程结果到达后局部 diff 更新,不要整表重建。
5. 根因结论
- 置信度:🟡 中。
- 一句话根因:iOS 报警页把「通知权限查询、当天报警全量 DB 读取、O(n×m) 去重、KMP 强制远程重拉第一页」四件事压在同一次页面进入的主线程路径上,任何一项变慢都会被人感知为「一进去就卡」。
- 关键证据链:
- 用户侧:4 条不同 iOS 版本、不同机型的独立反馈都指向报警页或 App 级卡顿。
- 代码侧:
viewWillAppear→loadData→ DB 全量读 → O(n×m) 去重的同步链,叠加 KMPpageDidAppear的强制远程重拉。 - 日志侧:
259780单日 37 次 ws 重建 + 46 次device/list请求,说明页面进入会被反复触发重拉。 - 未闭环处:本期两份 Logan 都没有卡顿时长数据,
259824的日志头部被截断(clogan header处即开始),因此「十几秒」这一数字来自用户描述,不是日志实测;通知权限阻塞也尚未通过 Instruments 证实。
6. 建议下一步
- 分配给:iOS 报警模块负责人 + KMP
moduleMessage负责人。 - 优先处理项:
- 按反馈
259824的机型(iPhone 27.0 / iOS 26)真机复现:清空通知权限后首次进入报警 Tab,抓 Instruments Time Profiler 与 Main Thread Checker,确认getNotificationSettingsWithCompletionHandler回调前主线程是否被阻塞。 - 在
AlarmMsgViewController.m:138、:432、:596、:1844与AlarmMessagePage.kt:977五处加耗时打点,先量化再优化。
- 验证方法:
- 100 条 / 500 条 / 1 000 条报警三档数据量下,首次进入报警页可见首帧 ≤ 500 ms。
- 前后台切换 20 次,报警页每次回前台不出现整表重建(可用
refreshCurrentHistoryUiState reason=page_return日志计数验证节流生效)。 - 通知权限
NotDetermined、Denied、Authorized三态各验证一次首屏时间,确认权限查询不再进入关键路径。 - 任务账本:沿用
T-20261027-171006-ff51(P1,captured)。
本期扫描全量(全部沉淀到知识库)
| # | 关键词 | 反馈数 | 分类 | 处置 |
|---|---|---|---|---|
| 1 | 长连接重建 / 报警卡 / 报警信息短缺 | 5 | 🔴 进雷达 | 详细分析见问题 1(259780、259617、259896、259911、259769) |
| 2 | 报警页进入卡顿 | 4 | 🟠 进雷达 | 详细分析见问题 2(259824 及同族) |
| 4 | 设备离线 / 老显示离线 | 11 | 🟡 单点或重复 | 与第 257 期同族;259893、259865、259832 已并入任务 T-20261027-171012-5d00 |
| 5 | 回放 / 录像 / 回看不可用 | 14 | 🟡 单点或重复 | iOS 与 Android 部分已在第 255~257 期覆盖;HarmonyOS 6 条无 Logan,待补证 |
| 6 | 移动侦测 / 人形不显示或不报警 | 2 | 🟤 产品建议 | 259922、259923(同账号重复提交),与任务 T-20261018-090818-00a1 同族 |
| 7 | 添加设备 / 配网 / 绑定冲突 | 3 | 🟡 单点 | 259909(录像机二维码已被他人绑定,属业务规则咨询)、259914、259760 |
| 8 | 画面看不到 / 只有图片 | 2 | 🟡 单点或重复 | 259902、259771;与任务 T-20261021-170533-1339、T-20261024-170603-cfd1 同族 |
| 9 | 声音 / 对讲 | 1 | 🟡 单点 | 259906,无 Logan |
| 10 | 客服 / 流量卡 / 无效内容 | 13 | 🟢 咨询或无效 | 259892、259915、259725、259735、259875、259867 等,无技术信息量 |
已折叠 1 条普遍性网络问题(含-102/-101/-1002与中/英/俄/法/西/葡/土/阿/日多语言网络提示模板,如Проверьте телефонную сеть、Please check your mobile network);全量明细见同名 Markdown 知识库。
说明:同一反馈可能同时落入「进雷达」与某一排除栏(例如 259824 既算报警页卡顿,也出现在其他关键词统计中),因此上表各栏之和大于去重后的 185 条。
应用市场反馈(2026-10-27 00:00–23:59)
| 商店 | 评论数 | 差评数 | 主要问题分类 | 处置 |
|---|---|---|---|---|
| App Store | 0 | 0 | 无 | 无评论 |
| 华为应用市场 | 0 | 0 | 无 | 无评论 |
| 应用宝 | 0 | 0 | 无 | 无评论 |
| Google Play | — | — | 采集失败 | 未配置代理,本期无法采集 |
| 荣耀 / vivo / OPPO / 小米 | — | — | 待导入 | 需人工后台导出评论文件 |
差评原文摘录:本窗口没有采集到应用市场评论。
采集状态:App Store 0 条、华为应用市场 0 条、应用宝 0 条;Google Play 失败(未配置代理);荣耀应用市场、vivo 应用商店、OPPO 软件商店、小米应用商店待导入。原始数据:knowledge/appstore-feedback/raw/2026-10-27.json。
注意:以上「0 条」是采集成功但确实无评论;Google Play 与四个手商店是采集未完成,属于数据盲区,不能等同于「用户没有意见」。本期进雷达的两个问题均来自自有反馈平台,未获得应用市场侧交叉印证。
数据源状态
| 数据源 | 状态 | 说明 |
|---|---|---|
| 自有反馈接口 | ✅ 正常 | total=207 / fetched=207 / complete=true / pages=5;窗口 2026-10-26 17:00:00~2026-10-27 17:00:00 内 185 条,其余 22 条为 17:00 之后新提交 |
| 应用市场(App Store / 华为 / 应用宝) | ✅ 正常 | 三家均返回 0 条 |
| 应用市场(Google Play) | ❌ 失败 | 未配置代理,本期无法采集 |
| 应用市场(荣耀 / vivo / OPPO / 小米) | ⏸️ 待导入 | 需人工后台导出评论文件 |
| 神策 | ⚠️ 部分降级 | query_sql 可用;SiotDevConnectResult 无 result 列(只有 error_code,且本期该列为空),AlarmMessage 事件名不存在,均已在正文标注口径限制,未用替代事件硬凑 |
| Logan | ✅ 可读 | 下载 3 份:259780(8 129 行)、259824(3 178 行)、259896(3 922 行);259824 头部为 clogan header,08:17 之前内容缺失 |
| 友盟 | ⏭️ 未查 | 本期无崩溃、ANR 类主诉;用户提到「偶尔闪退」但无崩溃栈,不满足触发条件 |
| TAPD | ⏭️ 未查 | 已用 Logan + 代码链路定位,不以历史 Bug 搜索替代现场证据 |
| 代码仓 | ✅ 已核对 | Seetong-App-iOS 分支 feature_v8.4.2;seetong-kmp 分支 feature_v8.4.2;Seetong-App-Android 分支 feature_v8.4.2 |
| 任务账本 | ✅ 已登记 | T-20261027-171012-c2c8、T-20261027-171006-ff51,均 P1 / captured;本期已更新 c2c8 的 next_action |
待补证
- 补采
259824(iPhone 27.0)的完整 Logan 前段:当前文件从 08:17:05 的clogan header开始,缺失进入报警页的实际时刻,无法给出卡顿时长。 - 在
WebSocketManager五处关键节点补打reConnectCount/reconnection/ 心跳状态与调用方堆栈后,灰度一批 iOS8.4.1.6用户,拿到「谁在 open 后立即 close」的直接证据。 - 取服务端侧 ws 会话时长与会话数统计,与客户端 37 次重建对齐,确认服务端是否也在同一时刻判定断开。
- 对
259896(iPhone 17.5.1,广东,卡回放无法播放 + 闪退)补采崩溃栈或Log0/Log1附件;本期该条只拿到 15:13 一次 SDK 初始化,不足以判断其闪退与长连接重建是否相关。 - HarmonyOS
1.1.2.3本期 6 条回放或离线反馈仍无 Logan,需在下期前补采至少 2 份。 - Google Play 与荣耀/vivo/OPPO/小米四个商店的采集缺口需补齐,否则应用市场侧长期是盲区。
下一期 = 第259期 = 2026-10-28-H17.md(明天下午 17:00;窗口 2026-10-27 17:00~2026-10-28 17:00)