Gerenciamento de chamadas em espera

O Vonage Client SDK não possui uma API específica para “colocação em espera”. Em vez disso, A função “hold” é implementada como uma combinação de “mute” e “earmuff”:

  • mute(callId) — interrompe o envio do seu áudio para o destinatário
  • enableEarmuff(callId) — deixa de receber áudio da outra parte

Para desmarcar, reverta ambos: chame unmute(callId) e disableEarmuff(callId).

No iOS e no Android, a interface de usuário de chamadas do sistema (CallKit / framework Telecom) oferece um botão de espera nativo. Os guias da plataforma abaixo mostram como conectar esse botão às chamadas de mudo + fone de ouvido do SDK.

Este guia irá orientá-lo ao longo do processo de implementação da funcionalidade de colocação de chamadas em espera em suas applications para iOS e Android, utilizando nosso SDK de VoIP.

Atualmente, a função de espera de chamada não é compatível com o Web SDK.

Integração de telecomunicações

Antes de começar este tutorial, certifique-se de ter integrado a estrutura Android Telecom ao seu aplicativo.

Você pode seguir o guia oficial aqui ou explore nosso aplicativo Android Voice Sample, disponível aqui.

Suporte à retenção por meio da implementação da conexão

Depois de criar sua implementação do Conexão turma, vocês precisarão adicionar o CAPABILITY_SUPPORT_HOLD para os recursos de conexão e substituir o onHold() e onUnhold() métodos.

Veja a seguir um exemplo em Kotlin:

class CallConnection(val callId: CallId) : Connection() {
    private lateinit var clientManager: VoiceClientManager
    var isOnHold = false
        private set

    init {
        connectionProperties = connectionProperties or PROPERTY_SELF_MANAGED
        connectionCapabilities = connectionCapabilities or CAPABILITY_SUPPORT_HOLD /** add other capabilities */
        audioModeIsVoip = true
    }

    // ... Other methods ...

    override fun onHold() {
        if (!isOnHold) {
            clientManager.holdCall(this)
        }
    }

    override fun onUnhold() {
        if (isOnHold) {
            clientManager.unholdCall(this)
        }
    }

    fun toggleHoldState() {
        isOnHold = !isOnHold
        if (isOnHold) setOnHold() else setActive()
    }
}

Interação com o SDK de voz

Para implementar o estado de espera de uma chamada, ative silenciar e protetor de orelhas simultaneamente.

O código a seguir dentro do VoiceClientManager A classe demonstra isso:

class VoiceClientManager(private val context: Context) {
    private lateinit var client : VoiceClient

    fun holdCall(call: CallConnection){
        call.apply{
            client.mute(callId){ error ->
                error?.let {
                    println("Error muting when holding call with id: $callId")
                } ?: run {
                    client.enableEarmuff(callId){ error ->
                        error?.let {
                            println("Error enabling earmuff when holding with id: $callId")
                        } ?: run {
                            println("Call $callId successfully put on hold")
                            toggleHoldState()
                        }
                    }
                }
            }
        }
    }

    fun unholdCall(call: CallConnection){
        call.apply{
            client.unmute(callId){ error ->
                error?.let {
                    println("Error unmuting when unholding call with id: $callId")
                } ?: run {
                    client.disableEarmuff(callId){ error ->
                        error?.let {
                            println("Error disabling earmuff unholding call with id: $callId")
                        } ?: run {
                            println("Call $callId successfully removed from hold")
                            toggleHoldState()
                        }
                    }
                }
            }
        }
    }
}

Fique à vontade para adaptar os trechos de código de acordo com sua implementação e seus requisitos específicos.

Integração com o Callkit

Antes de começar este tutorial, certifique-se de ter integrado a estrutura Callkit ao seu aplicativo.

Você pode acompanhar o guia oficial, ou explore nosso aplicativo de amostras de voz para iOS, disponível aqui.

Suporte à retenção por meio do CXUpdate

Depois de criar seu CallController classe, que contém uma referência a um CXProvider e um CXCallController você precisará ativar o supportsHolding bandeira na CXCallUpdate tanto para chamadas feitas quanto para chamadas recebidas.

Veja a seguir um exemplo em Swift:

import CallKit

class CallController {
    let callProvider: CXProvider
    let cxController = CXCallController()

    // ... Other methods ...

    func reportOutgoingCall(callId: String){
        self.callProvider.reportOutgoingCall(with: callId, connectedAt: Date.now)
        let update = CXCallUpdate()
        /** add other capabilities */
        update.supportsHolding = true
        self.callProvider.reportCall(with: callId, updated: update)
    }

    func reportIncomingCall(callId: String){
        let update = CXCallUpdate()
        /** add other capabilities */
        update.supportsHolding = true
        self.callProvider.reportNewIncomingCall(with: callId, update: update)
    }
}

Interação com o SDK de voz

Depois de criar seu CXProviderDelegate implementação, ouça o CXSetHeldCallAction para colocar chamadas em espera usando o Voice SDK.

Para implementar o estado de espera de uma chamada, ative silenciar e protetor de orelhas simultaneamente.

O código a seguir dentro do CallController A classe demonstra isso:

import VonageClientSDKVoice

class CallController: NSObject {
    let callProvider: CXProvider
    let cxController = CXCallController()
    let client: VGVoiceClient
    var activeCalls: [UUID: String] = [:] // Maps CallKit UUID to Vonage callId

    // ... initialization and other methods ...
}

extension CallController: CXProviderDelegate {

    func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
        guard let callId = self.activeCalls[action.callUUID] else {
            action.fail()
            return
        }
        if action.isOnHold {
            self.client.mute(callId) { error in
                if let error = error {
                    print("Error muting when holding call: \(error)")
                    return
                }
                self.client.enableEarmuff(callId) { error in
                    if let error = error {
                        print("Error enabling earmuff when holding call: \(error)")
                        return
                    }
                    print("Call \(callId) successfully put on hold")
                }
            }
        } else {
            self.client.unmute(callId) { error in
                if let error = error {
                    print("Error unmuting when unholding call: \(error)")
                    return
                }
                self.client.disableEarmuff(callId) { error in
                    if let error = error {
                        print("Error disabling earmuff when unholding call: \(error)")
                        return
                    }
                    print("Call \(callId) successfully removed from hold")
                }
            }
        }
        // CallKit requires fulfilling the action synchronously
        action.fulfill()
    }
}

Fique à vontade para adaptar os trechos de código de acordo com sua implementação e seus requisitos específicos.