Reconnection and Network Resilience
Network switches and short connectivity drops can interrupt call media. The SDK handles reconnection automatically in most cases — use media lifecycle events and reconnect APIs to keep users informed and recover where possible.
How Automatic Reconnection Works
When the SDK detects a media interruption (ICE connection failure, network switch), it automatically attempts to restore the connection by performing an ICE restart on the peer connection.
Timing and Retry Behavior
| Parameter | Value | Description |
|---|---|---|
| Max automatic retries | 5 | The SDK retries up to 5 times before giving up |
| Retry interval | 3 seconds | Fixed delay between each reconnection attempt (no exponential backoff) |
| Media timeout | 10 seconds | If no media is established within 10s of a connection attempt, the SDK treats it as failed |
| Total automatic recovery window | ~15 seconds | 5 retries x 3s interval = up to 15s of automatic recovery before failure |
What Happens at Each Stage
-
Reconnecting — The SDK detects a media interruption and fires
onCallMediaReconnecting. It performs up to 5 ICE restart attempts, spaced 3 seconds apart. No developer action is needed during this phase. -
Reconnected — If any retry succeeds, the SDK fires
onCallMediaReconnection. The audio stream is restored and the call continues normally. -
Failed — If all 5 automatic retries are exhausted, or if the server returns an error during reconnection, the SDK fires
onCallMediaDisconnect. At this point:- Audio has stopped
- The call session may still be active on the server
- The developer can attempt manual recovery with
reconnectCall(callId)if network connectivity has returned - If no recovery occurs, the server will eventually terminate the call and
onCallHangupfires withmediaTimeoutreason
Developer action summary
- During reconnecting: No action required. Show a "reconnecting" UI indicator.
- On reconnection success: Remove the indicator, return to normal call UI.
- On disconnect (failure): Optionally attempt
reconnectCall(callId)if you detect network is back. Otherwise, inform the user the call was lost.
Session-Level Reconnection
Separately from media reconnection, the SDK also automatically reconnects the WebSocket session when connectivity drops:
| Parameter | Value |
|---|---|
| Max reconnection attempts | 5 |
| Reconnection delay | 5 seconds (with 0.75 randomization factor) |
Session reconnection fires onReconnecting and onReconnection events (distinct from the call media events above).
onCallMediaDisconnect
Fires when the media connection is terminally lost — after all 5 automatic reconnection attempts have been exhausted, or after an unrecoverable server error. At this point the audio stream has stopped, but the call session may still be active on the server. You can attempt manual recovery with reconnectCall(callId).
client.on(
'callMediaDisconnect',
(callId: string, reason: CallDisconnectReason) => {
if (reason === 'networkChange') {
console.log(`Call ${callId} was disconnected due to a network change`);
} else {
exhaustiveCheck(reason);
}
}
);
client.setOnCallMediaDisconnectListener { legId, reason ->
when (reason) {
CallDisconnectReason.networkChange -> println("Received call media disconnect $reason for Call $legId")
}
}
client.setOnCallMediaDisconnectListener((legId, reason) -> {
if (reason == CallDisconnectReason.networkChange) {
System.out.println("Received call media disconnect " + reason + " for Call " + legId);
}
return null;
});
func voiceClient(_ client: VGVoiceClient, didReceiveMediaDisconnectForCall callId: VGCallId, reason: VGCallDisconnectReason) {
print("leg \(callId) has received media disconnect for \(reason)")
}
- (void) voiceClient:(VGVoiceClient *)client didReceiveMediaDisconnectForCall:(VGCallId)callId reason:(VGCallDisconnectReason)reason {
NSLog(@"Leg %@ has received media disconnect for reason %ld", callId, reason);
}
onCallMediaReconnecting
Fires when the SDK detects a media interruption (such as a network switch between Wi-Fi and cellular) and is automatically attempting to restore the connection. No user action is required — show a "reconnecting" indicator in your UI.
client.on('callMediaReconnecting', (callId) => {
console.log(`Call media is reconnecting for call ${callId}`);
});
client.setOnCallMediaReconnectingListener { legId ->
println("Received call media reconnecting for Call $legId")
}
client.setOnCallMediaReconnectingListener((legId) -> {
System.out.println("Received call media reconnecting for Call " + legId);
return null;
});
func voiceClient(_ client: VGVoiceClient, didReceiveMediaReconnectingForCall callId: VGCallId) {
print("leg \(callId) is Reconnecting")
}
- (void) voiceClient:(VGVoiceClient *)client didReceiveMediaReconnectingForCall:(VGCallId)callId {
NSLog(@"Leg %@ is reconnecting", callId);
}
onCallMediaReconnection
Fires when the SDK successfully restores the media connection after an interruption. Remove the reconnecting indicator and return to normal call UI.
client.on('callMediaReconnection', (callId) => {
console.log(`Call media is reconnected for call ${callId}`);
});
client.setOnCallMediaReconnectionListener { legId ->
println("Received call media reconnection for Call $legId")
}
client.setOnCallMediaReconnectionListener((legId) -> {
System.out.println("Received call media reconnection for Call " + legId);
return null;
});
func voiceClient(_ client: VGVoiceClient, didReceiveMediaReconnectionForCall callId: VGCallId) {
print("leg \(callId) has received media reconnection")
}
- (void) voiceClient:(VGVoiceClient *)client didReceiveMediaReconnectionForCall:(VGCallId)callId {
NSLog(@"Leg %@ has received media reconnection", callId);
}
Manual Reconnect
Use reconnectCall(callId) when your app decides to trigger recovery explicitly — for example, after receiving onCallMediaDisconnect and confirming that network connectivity has returned.
Manual reconnection also follows the same retry logic (up to 5 attempts, 3s apart) once triggered.
const callId = 'callId';
await client.reconnectCall(callId);
// Callback
client.reconnectCall("callId") {
it?.let { err ->
// Handle Error in reconnecting call
println("Error in reconnecting call: $err")
}
}
// Coroutine
try {
client.reconnectCall("callId")
}
catch (e:Error) {
// Handle Error in reconnecting call
}
client.reconnectCall("callId", it -> {
if (it != null) {
// Handle Error in reconnecting call
System.out.println("Error in reconnecting call: " + it);
}
return null;
});
// Callback
client.reconnectCall("someCallId") { error in
guard error != nil else {
print("Failed to reconnect \(error?.localizedDescription ?? "")")
return
}
}
/// Async Await
Task.detached {
do {
try await client.reconnectCall("someCallId")
}
catch {
print("error")
}
}
[client reconnect:@"someCallId" callback:^(NSError * _Nullable error) {
if(error){
NSLog(@"Failed to reconnect: %@", error);
}
}];
Android Requirement
Automatic network-change recovery on Android requires:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Failure Behavior and UX
- If all automatic retries fail and no manual reconnection succeeds,
onCallHangupeventually fires withmediaTimeoutreason. - Show a reconnecting indicator when
onCallMediaReconnectingfires. - Return to normal call UI only after
onCallMediaReconnectionfires. - On
onCallMediaDisconnect, inform the user and optionally offer a "Retry" button that callsreconnectCall(callId).