CallStore
Introduction
Audio/video call functionality is implemented through
CallStore for real-time audio/video interaction between users. CallStore provides a comprehensive set of APIs to manage the entire call lifecycle. When integrating CallStore, please be aware of the following runtime characteristics:Error Handling: When actively calling an API (e.g.,
calls), if the call itself fails due to parameter validation or state conflicts, you will typically be notified via an asynchronously thrown error event or a returned error code. Network or remote-side anomalies are also delivered through onCallEnded with the error reason attached.Threading Model & Cleanup: All state updates (
CallState) and event callbacks (CallEvent / CallEventListener) are typically guaranteed to fire on the main thread, so they can be used directly to refresh the UI. Under the global singleton pattern, be sure to unregister listeners when components are destroyed (e.g., deinit / onDestroy) to avoid memory leaks.Important:
Ensure the SDK is initialized before accessing the shared singleton. Do not instantiate it directly, as doing so will prevent you from receiving call state updates.
Note:
Call state updates are delivered through the state publisher. Subscribe to it to receive real-time updates of call data.
Warning:
Please ensure proper handling of UI state after the call ends to avoid UI anomalies.
Features
Create Audio/Video Calls: Support initiating audio or video calls to one or multiple users, with configurable timeout, custom data, and other parameters.
Answer/Reject Audio/Video Calls: When receiving an incoming call invitation, you can choose to answer or reject.
Hang Up Audio/Video Calls: End the current ongoing audio/video call.
Group Call Management: Support joining existing group calls or inviting other users to join during a call.
Call History Management: Query recent call records (with pagination support), delete specified call records.
Event-Driven Architecture: Provides event listeners for call started, call received, call ended, etc.
State Subscription: Real-time subscription to current call state, including participant list, volume information, network quality, etc.
Subscribable Data
CallState fields are described below:
Property | Type | Description |
activeCall | Current active call information.
Lifecycle Contract: When onCallEnded is triggered, this object is not immediately cleared; instead, it retains the call's final state for the UI to display end animations (at this point CallInfo.result or other parameters reflect the end reason). If a new call is initiated or received, it will be automatically overwritten. Developers can manually clean up by resetting the related CallStore state. | |
recentCalls | Recent call records list. Note: Each call to queryRecentCalls currently behaves as an overwrite update rather than an automatic append. To implement infinite scrolling, the business layer needs to concatenate newly arrived data with the existing list on its own. | |
cursor | String | Pagination cursor, used to query more call records. |
selfInfo | Current user's own information. | |
allParticipants | All participants in current call. | |
speakerVolumes | [String: Int] | Participant volume information, key is user ID, value is volume level. |
networkQualities | [String: NetworkQuality] | Participant network quality information, key is user ID, value is network quality. |
API List
Function | Description |
Get the CallStore singleton instance. | |
Call event publisher. | |
Create a call. | |
Answer a call. | |
Reject a call. | |
Hang up a call. | |
Join a group call. | |
Invite users to join a call. | |
Query recent call records. | |
Delete call records. |
Get Instance
shared
Get the CallStore singleton instance.
Observe State and Events
callEventPublisher
Call event publisher.
Call Operations
calls
Create an audio or video call to specified users, supporting both one-on-one and group calls.
calls(participantIds: string[],mediaType: CallMediaType,params: CallParams | undefined,): Promise<void> {return this.impl.calls(participantIds, mediaType, params)}
Version
Supported since version 3.5.
Parameters
Parameter | Type | Description |
participantIds | [String] | List of callee IDs, supports single or multiple users. |
mediaType | Call media type (audio/video). | |
params | Call parameter configuration. |
accept
Answer a call. Call this method to answer the call when receiving an incoming call invitation.
accept(): Promise<void> {return this.impl.accept()}
Version
Supported since version 3.5.
reject
Reject a call. Call this method to reject the call when receiving an incoming call invitation.
reject(): Promise<void> {return this.impl.reject()}
Version
Supported since version 3.5.
hangup
Hang up and end the current ongoing call.
hangup(): Promise<void> {return this.impl.hangup()}
Version
Supported since version 3.5.
join
Join an ongoing group call using a specific call ID.
join(callId: string): Promise<void> {return this.impl.join(callId)}
Version
Supported since version 3.5.
Parameters
Parameter | Type | Description |
callId | String | Call ID to join. |
invite
Invite other users to join during an ongoing call.
invite(participantIds: string[],params: CallParams | undefined,): Promise<void> {return this.impl.invite(participantIds, params)}
Version
Supported since version 3.5.
Parameters
Parameter | Type | Description |
participantIds | [String] | List of invitee IDs. |
params | Call parameter configuration. |
Call History
queryRecentCalls
Query recent call records.
Current Limitation: Currently, query results overwrite (reset) the
state.recentCalls list each time, rather than automatically appending.queryRecentCalls(cursor: string, count: number): Promise<void> {return this.impl.queryRecentCalls(cursor, count)}
Version
Supported since version 3.5.
Parameters
Parameter | Type | Description |
cursor | String | Pagination cursor, pass empty string for first query. |
count | UInt | Query count. |
deleteRecentCalls
Delete specified call records.
deleteRecentCalls(callIdList: string[]): Promise<void> {return this.impl.deleteRecentCalls(callIdList)}
Version
Supported since version 3.5.
Parameters
Parameter | Type | Description |
callIdList | [String] | List of call IDs to delete. |
Data Structures
CallMediaType
Call media type, used to specify whether to initiate an audio call or video call.
Enum Value | Value | Description |
audio | 1 | Audio call. |
video | 2 | Video call. |
CallEndReason
Call end reason, used to identify how the audio/video call ended (normal hangup, rejection, timeout, etc.).
Enum Value | Value | Description |
unknown | 0 | Unknown reason. |
hangup | 1 | Normal hangup. |
reject | 2 | Rejected. |
noResponse | 3 | No response. |
offline | 4 | Offline. |
lineBusy | 5 | Line busy. |
canceled | 6 | Call was canceled. |
otherDeviceAccepted | 7 | Accepted on another device. |
otherDeviceReject | 8 | Rejected on another device. |
endByServer | 9 | Call ended by backend. |
CallDirection
Call direction, used to identify whether the call is incoming, outgoing, or missed.
Enum Value | Value | Description |
unknown | 0 | Unknown. |
missed | 1 | Missed call. |
incoming | 2 | Incoming call. |
outgoing | 3 | Outgoing call. |
CallParticipantStatus
Call participant status, used to identify whether the participant is waiting or has answered.
Enum Value | Value | Description |
none | 0 | No status (not in call). |
waiting | 1 | Waiting (calling/being called). |
accept | 2 | Accepted. |
CloudRecordPolicy
Cloud recording policy for audio/video calls, used to configure whether to enable cloud recording for a specific call.
Enum Value | Value | Description |
followConsoleConfig | 0 | Follow the global configuration in the console (default). |
enable | 1 | Enable cloud recording, overriding the console configuration. |
disable | 2 | Disable cloud recording, overriding the console configuration. |
CallEventListener
Call events, used to receive various event notifications during a call.
Methods
Method | Description |
onCallStarted | Callback when a call event starts.
Timing Note: This indicates that "the current call flow has been successfully entered (e.g., calls was initiated and accepted internally)," but it does not mean the audio/video room has been connected or established. It is recommended to use this only for the initial UI navigation (on the caller side). |
onCallReceived | Callback when a new call invitation is received.
Field Reading Recommendation: The event parameters only pass through callId, mediaType, and userData. If you need to read the full information such as the inviter, room ID, or associated group ID, please read it from state.activeCall after receiving this event. |
onCallEnded | Unified callback for call ending events.
Multi-scenario Note: Whether it's a hangup after connection, a no-answer timeout, cancellation by the remote side, or the call being answered on another device, this event will ultimately be triggered. Developers must check the reason parameter to determine the specific cause and display the corresponding UI text or handle branching logic.
Getting Call Duration: This event's parameters do not include a call duration field. To get the call duration, read state.activeCall.duration when this callback is received (unit: seconds). After the call is connected, the SDK internally increments this value every second; when the call ends, activeCall is not immediately cleared, so it can be safely read within this callback. |
onSuggestSwitchToCellular | Callback when the system detects poor WiFi quality and recommends switching to cellular network. |
CallParams
Call parameter configuration, used to set room ID, timeout, custom data, and other parameters when initiating an audio/video call.
Property | Type | Description |
roomId | String | TRTC room ID (CallStore's media stream management uses Tencent Cloud TRTC service). Optional parameter.
When not provided, it is automatically generated by the server; if your app needs to specify or reuse a TRTC room, you can pass in a specific string. |
timeout | Int | Ring timeout duration (seconds). Optional parameter.
Only controls the unanswered timeout phase from call initiation ( calls) to answer. Does not apply to already connected calls or invite operations.
When set to 0, the server default (30s) will be used. |
userData | String | Custom pass-through data attached when making a call. Optional parameter.
This data is primarily exposed to the callee's business logic via the onCallReceived event.Note: It does not enter the long-term CallInfo state, nor is it persisted to call records. It is recommended to pass a short JSON string. |
chatGroupId | String | Tencent Cloud IM group ID. Optional parameter.
Only needs to be provided in the "call initiated from a group chat" scenario. When provided, the system will route signaling and associate this call with the group's call records, for sending call start/end status messages in the group chat and for inviting group members to join the call during the call.
For one-on-one calls, or ad-hoc multi-party calls not bound to a specific group, always leave this empty. Note: This field takes effect on the initial calls invocation; subsequent invite parameters cannot change the group bound to this call. |
isEphemeralCall | Bool | Ephemeral call. Optional parameter.
When set to true, no call message will be generated after this call ends. Common scenario: initiating a call in a 1v1 chat without displaying the call message. |
cloudRecordPolicy | Cloud recording policy for this call. Prerequisite: the relevant capability must already be enabled in the console. followConsoleConfig (default): Follow the global configuration in the console. enable: Force-enable cloud recording, overriding the global configuration in the console. disable: Force-disable cloud recording, overriding the global configuration in the console. | |
offlinePushTitle | string | Offline push notification title.
When not empty, overrides the default title (login user's nickname). |
offlinePushDescription | string | Offline push notification description.
When not empty, overrides the default description. |
CallParticipantInfo
Call participant information, including user ID, nickname, avatar, participation status, microphone/camera on/off status, etc.
Property | Type | Description |
id | String | User ID. |
name | String | User nickname. |
avatarURL | String | User avatar URL. |
remark | String | Friend remark. |
status | Participant status. | |
isMicrophoneOpened | Bool | Whether microphone is on. |
isCameraOpened | Bool | Whether camera is on. |
CallInfo
Call information, including call ID, room ID, initiator, invitees, media type, call direction, start time, duration, and other complete information.
Property | Type | Description |
callId | String | Call ID. |
roomId | String | Room ID. |
inviterId | String | Initiator ID. |
inviteeIds | [String] | Invitee ID list. |
chatGroupId | String | Chat group ID. |
mediaType | Call media type. Note: May be null (null / nil) during early event stages, when the type is unknown, or when historical call records (recent calls) have not fully back-filled this field. Handle optional unwrapping accordingly. | |
result | Call direction / record type (e.g., incoming, outgoing, missed). Note: This does not represent the specific reason for call termination. For end reasons, refer to the CallEndReason enum. | |
startTime | TimeInterval | Timestamp of when the call was actually connected (unit: milliseconds). |
duration | TimeInterval | Call duration (seconds). |
CallState
Call state data, manages the real-time data state of the current call.
Property | Type | Description |
activeCall | Current active call information.
Lifecycle Contract: When onCallEnded is triggered, this object is not immediately cleared; instead, it retains the call's final state for the UI to display end animations (at this point CallInfo.result or other parameters reflect the end reason). If a new call is initiated or received, it will be automatically overwritten. Developers can manually clean up by resetting the related CallStore state. | |
recentCalls | Recent call records list. Note: Each call to queryRecentCalls currently behaves as an overwrite update rather than an automatic append. To implement infinite scrolling, the business layer needs to concatenate newly arrived data with the existing list on its own. | |
cursor | String | Pagination cursor, used to query more call records. |
selfInfo | Current user's own information. | |
allParticipants | All participants in current call. | |
speakerVolumes | [String: Int] | Participant volume information, key is user ID, value is volume level. |
networkQualities | [String: NetworkQuality] | Participant network quality information, key is user ID, value is network quality. |
Usage Example
import AtomicXCore// Create a video callCallStore.shared.calls(participantIds: ["mike"], mediaType: .video, params: nil) { code, message in}
