事件與錯誤處理
本頁講怎樣訂閱事件、全部事件的分類、錯誤物件 DRException,以及日誌和診斷。
需要一直顯示的資料(會話列表、未讀數、連線狀態),優先訂閱對應的 StateFlow 或列表快照。事件適合觸發一次性的動作:彈提示、跳轉、診斷,或處理臨時訊息;不要把事件當作唯一的資料來源。
| 要做什麼 | 看哪裡 |
|---|---|
| 訂閱事件 | 訂閱事件 |
| 查有哪些事件 | 事件分類 |
| 判斷錯誤、處理取消 | DRException |
| 開日誌、匯出診斷資訊 | 日誌與診斷 |
訂閱事件
import com.deeprespond.im.*
im.on<DREvent.MessageSendFailed>().collect { event ->
println("${event.clientMsgId}: ${event.error.code}")
}- 也可以用
im.on(DREvent.MessageReceived::class),或收集全部事件im.events。 - 在跟隨生命週期的協程中收集,頁面停止時取消。
- 事件流(
SharedFlow)的緩衝有限,不能當作永不丟失的訊息佇列。 - App 啟動階段發出的事件會暫存,交給第一個訂閱者;
startupEvents讀取並清空這些事件。請在一個統一的地方訂閱,以免多個頁面各自處理同一個啟動跳轉。
事件分類
| 類別 | 主要事件 |
|---|---|
| 登入與連線 | AuthStateChanged、ConnectionStateChanged、SyncCompleted、SyncFailed |
| 儲存與配置 | StorageReset、StorageFull、StorageModeChanged、ConfigChanged、SdkUpgradeRequired |
| 使用者與裝置 | MeChanged、MeMuteChanged、UsersChanged、DevicesChanged、DevicesNewLogin |
| 前後臺與時區 | AppStateChanged、ClientStateReported、TimezoneChanged |
| 會話與訊息 | ConversationsChanged、ConversationsUnreadChanged、MessagesChanged、MessageReceived、MessageSendFailed、MessageOnline、TypingChanged、ReceiptsChanged |
| 好友與群 | FriendsChanged、BlacklistChanged、FriendRequestsChanged、GroupsChanged、GroupMembersChanged、GroupRequestsChanged |
| 推送與線上 | PushChanged、PresenceChanged、PresenceSubscribeFailed |
| 通話 | CallIncoming、CallChanged、GroupCallChanged |
原生推送的 opened、registrations 和系統通話的 actions 在各自的控制器上,聊天室的事件在聊天室控制代碼上。全部事件的欄位見資料型別。
DRException
import com.deeprespond.im.*
import kotlinx.coroutines.CancellationException
try {
im.messages.send(SendTarget.User("bob"), OutgoingContent.Text("你好"), SendOptions(waitUntilSent = true))
} catch (error: CancellationException) {
throw error // 保持 Kotlin 协程取消语义。
} catch (error: DRException) {
println("${error.code}/${error.reason}; request=${error.requestId}")
}| 欄位 | 含義 |
|---|---|
| code、reason | 錯誤碼及 details.reason,業務按它們判斷 |
| details | 原始 JsonObject 附加資訊 |
| source | HTTP、WS、LOCAL |
| status | HTTP 狀態,長連線和本地失敗可能為 null |
| requestId | 排查請求的 ID |
| retryAfter | Kotlin Duration;Java 用 retryAfterMillis |
SDK 自己的常見錯誤碼:network_error、timeout、aborted、not_signed_in、not_connected、local_validation、storage_error、unsupported、permission_required、device_error、invalid_state、send_abandoned。服務端返回的錯誤見錯誤碼。
- 取消協程會丟擲
CancellationException,SDK 不會把它包裝成普通的業務錯誤。像上例那樣先單獨捕獲並重新丟擲,保持協程的取消行為。 - 寫操作已經發出、或訊息已經進入傳送佇列後,取消等待不會撤銷服務端的操作;上傳、下載要呼叫任務自己的
cancel。 - 遇到
rate_limited時按retryAfter等待,不要無限重試。
日誌與診斷
LogOptions 可以設定 level、sink、file。預設級別為 WARN;可以開啟寫入檔案,或把 LogEntry 交給你自己的日誌系統。每條日誌帶有 module、code、reason、requestId、connectionId。
val info = im.connection.diagnostics()
val archive = im.exportDiagnostics()
println(info.connection)
println(archive.name)- 診斷資訊包括連線、最近的斷線和失敗、同步時間、儲存模式、時鐘偏差和傳送佇列的大小。
exportDiagnostics()把它們打包成快取目錄中的 ZIP 檔案,SDK 會清理過期的檔案。請透過 App 的 FileProvider 分享,不要暴露私有目錄的絕對路徑。- 日誌和診斷用於排查問題,不要往裡寫密碼、憑證或訊息內容。
describeError、renderRecall 等提示輔助見介面與生命週期。
頻道狀態
獨立頻道的狀態從 StateFlow 讀取:im.channels.current、handle.snapshot、handle.tracks,頁面結束時取消觀察。
- 頻道沒有呼叫和振鈴,不要用通話的
CallIncoming、CallChanged事件判斷頻道的狀態。 - 取消加入的協程會釋放已佔用的名額;
leave的請求即使失敗,本地的麥克風和攝像頭也會停止。
見頻道接入。
簡體、繁體與英語提示
SDK 自帶簡體中文、繁體中文和英語的提示文字,預設簡體中文,不呼叫線上翻譯:
| 平臺 | 用法 |
|---|---|
| Android | DRLocale.en、DRLocale.zhTW、DRLocale.forLanguage(tag) |
| Web | @deeprespond/im-web/locale 的 createLocale()、describeError() |
| Flutter | 從 render.dart 匯入 en、zhTW、localeForLanguage(tag) |
把選好的文案表交給顯示輔助函式即可,使用者選擇的語言由你的 App 儲存。切換語言只改變提示文字,錯誤碼和使用者發的內容不變。
服務端的錯誤可能帶 message_key 和 message_params(用於生成本地化的提示),判斷錯誤時仍然用 code、reason 和 details。詳細的入口和語言的選擇規則見語言與本地化。
