Skip to content

Call lifecycle ​

Use lifecycle callbacks to keep call UI synchronized with real-time call progress. The diagrams below show the two main perspectives: placing a call and receiving one.

Outbound call (caller perspective) ​

When your app calls serverCall(), the callee leg progresses through status updates reported by onLegStatusUpdate.

Inbound call (callee perspective) ​

When your app receives a call invite, the local call transitions through invite handling into an active call.

Callback sources ​

Status updates ​

onLegStatusUpdate provides callee leg progression (for example: ringing -> answered -> completed). This is most relevant for outbound calls where you want to reflect the callee's state in your UI.

client.setOnLegStatusUpdate { call, legId, status ->
    when(status) {
        LegStatus.ringing -> println("Leg $legId for call $call is ringing")
        LegStatus.answered -> println("Leg $legId for call $call was answered")
        LegStatus.completed -> println("Leg $legId for call $call was completed")
    }
}

Initiating hangup ​

Use hangup to terminate your call.


// Callback
client.hangup("callId") {
    it?.let { err ->
        // Handle Error hanging up call
        println("Error hanging up call: $err")
    }
}

// Coroutine
try {
    client.hangup("callId")
} catch (e: Error) {
    // Handle Error hanging up call
}

Handling hangup errors ​

hangup() can fail if the call has already ended, the session expired, or there is a network issue. Always handle the error to ensure your UI transitions to the ended state regardless:

kotlin
client.hangup(callId) { error ->
    if (error != null) {
        // Hangup request failed — but the call may still end via server-side timeout.
        // Clean up local UI anyway to avoid a stuck call screen.
        println("Hangup error: ${error.message}")
    }
    // Always transition to end-of-call UI
    showCallEndedUI()
}

TIP

Even if hangup() fails, always clean up your local call state and UI. The server will terminate the call independently via timeout if the client-side hangup did not reach it. Waiting for onCallHangup as a secondary confirmation is good practice.

Receiving hangup events ​

Use onCallHangup to handle final call teardown and UI cleanup.


client.setOnCallHangupListener { call, callQuality, reason ->
    println("Received $reason callQuality: $callQuality for Call $call")
}

Debugging lifecycle events

If call events are not arriving as expected, enable verbose logging during development to trace lifecycle transitions. See Logging and diagnostics for full configuration options including custom loggers and topic filtering.

NCCO hangup behavior

  • connect NCCO behaves like standard two-party calling — when one party hangs up, the point-to-point connection ends and both legs are terminated.
  • conversation NCCO behavior is conversation-scoped — hanging up only removes that participant's leg from the shared room. Other participants remain connected until they leave individually.

Built with VitePress.