主题
Call Session、RTC Provider 与崩溃恢复
XHIM 把通话分为两层:
- Call Session 控制面:由 XHIM Server、Core 和各端 Facade 提供, 负责邀请、接听、拒绝、结束、有序信令和崩溃恢复;
- RTC 媒体面:由购买方注入的
RtcProvider实现,可适配客户 已选定的云 RTC 或私有化媒体服务。
SDK 不内置某家厂商凭证,也不会把 RTC token、endpoint 或供应商 credential 写入 SQLite、日志、分析或崩溃报告。
1. 公开 API
| api-id | 用途 | 关键输入 | 返回 |
|---|---|---|---|
call.invite | 邀请 1...64 个会话成员 | media kind、participants、conversation/call/mutation ID | XHIMCallSession |
call.accept | 接听 ringing 会话 | call ID、mutation ID | XHIMCallAcceptResult |
call.reject | 拒绝 ringing 会话 | call ID、reason、mutation ID | ended XHIMCallSession |
call.end | 结束 active 会话 | call ID、reason、mutation ID | ended XHIMCallSession |
call.list_signals | 显式读取指定 offset 之后的信令 | after offset、limit | XHIMCallSignalPage |
call.recover | 从当前账号持久游标执行一页崩溃恢复 | limit | XHIMCallSignalPage |
callID 和 mutationID 都是幂等身份。只有在重试同一语义操作时 才能复用;新操作必须使用新 mutationID。
2. 邀请与接听
swift
let session = try await client.inviteCall(
mediaKind: .video,
participantUserIDs: [peerUserID],
mutationID: UUID().uuidString.lowercased(),
conversationID: conversationID
)
let accepted = try await client.acceptCall(
callID: session.callID,
mutationID: UUID().uuidString.lowercased()
)
try accepted.rtcCredentials.withUserTokenString { token in
// 只在这个同步闭包内交给客户 RtcProvider。
rtcProvider.join(
roomID: accepted.rtcCredentials.roomID,
token: token,
endpoint: accepted.rtcCredentials.endpoint
)
}XHIMRTCCredentialLease 故意不实现 Codable,它的 description/debug output 对 room、token 和 endpoint 脱敏。应用在使用前检查 isExpired,不要把 token 复制到 UserDefaults、Keychain 外的持久存储、日志、Crash 或 APM 字段。
3. 状态机和有序性
text
ringing --accept--> active --end--> ended
| ^
+------reject----------+ended 是终态。服务端、Core 投影和页面都不得用迟到的旧信令将它 恢复为 ringing/active。XHIMCallSignal.offset 是账号信令页的持久顺序, sequence 是单个 call 的状态顺序,两者不能混用。
4. 崩溃、断网与进程重启恢复
App 完成登录并进入 ready 后,执行:
swift
var page = try await client.recoverCallSessions(limit: 200)
applyRecoveredSessions(page.activeSessions)
while page.hasMore {
page = try await client.recoverCallSessions(limit: 200)
applyRecoveredSessions(page.activeSessions)
}recoverCallSessions 不接受 App 传入的 offset。Core 把信令页、去重状态投影和 next offset 在同一 SQLite 事务中提交;进程在任何一步崩溃时,下次会 从上一个已提交游标继续。返回的 activeSessions 永远不包含 ended 会话。
listCallSignals 是显式分页查询,不推进 Core 恢复游标;不要用它替代恢复 API。
5. 取消语义
六个 API 都使用平台通用请求取消:Swift Task / XHIMRequest、 Android Java CompletableFuture.cancel(...)(Kotlin 兼容入口取消 coroutine)、 .NET CancellationToken、HarmonyOS request ID、Electron/Web AbortSignal。取消保证本地 completion 只结束一次并屏蔽迟到回调,但不是 服务端事务回滚;已被服务端接纳的 mutation 仍可能完成,最终状态由下一次 call.recover 收敛。
6. 发布验收
Call Session 源码和单元测试不等于真实音视频商用验收。客户选定 RTC Provider 后还必须覆盖:
- iOS/macOS、Android、Windows、HarmonyOS 之间的真机互通;
- 前后台、锁屏、杀进程、来电中断、蓝牙/听筒切换;
- 丢包、弱网、断网重连、token 过期和 provider 故障注入;
- 群通话人数、带宽、CPU/电量、崩溃率和客户隐私/录音合规。
在完成上述真机矩阵前,准确表述是“Call Session 控制面可用”,不是 “已经提供某家 RTC 的商用媒体质量承诺”。