Solução de problemas

Problemas conhecidos

Esta seção oferece uma visão geral concisa dos problemas conhecidos específicos de plataforma, dispositivo e navegador que podem surgir ao integrar o Vonage Client SDK às suas aplicações web.

Client SDK Integration

User Media Devices Not Being Released

Foi identificado um problema no Safari em que os dispositivos de mídia do usuário não são liberados, mesmo após o término da conexão entre pares. Isso pode levar a comportamentos inesperados e ao uso indevido de recursos. Leve isso em consideração ao implementar suas aplicações web utilizando o Vonage Client SDK para Web.

Esta seção oferece uma visão geral concisa dos problemas conhecidos, específicos da plataforma e do dispositivo, que podem surgir ao integrar o Vonage Client SDK aos seus aplicativos para Android.

Voice SDK Integration

Handling isIncomingCallPermitted Exception

Se você estiver usando o isIncomingCallPermitted Ao utilizar esse método do TelecomManager, esteja ciente de que ele pode lançar exceções em determinados dispositivos, como os da Xiaomi. Para garantir um funcionamento sem problemas, recomenda-se colocar essa chamada de método dentro de um bloco try-catch e definir um valor padrão como “true” no caso de ocorrer uma exceção. Caso contrário, o aplicativo poderá enfrentar problemas ao realizar chamadas. Veja como você pode implementá-lo:

// Get the TelecomManager instance
val telecomManager = context.getSystemService(AppCompatActivity.TELECOM_SERVICE) as TelecomManager

// Check permissions for incoming calls and handle exceptions
val isIncomingCallPermitted = try {
    telecomManager.isIncomingCallPermitted(phoneAccountHandle)
} catch (_: Exception) {
    // Exception occurred, default to true
    true
}

Ao adotar essa abordagem, seu aplicativo poderá lidar de maneira adequada com possíveis exceções, garantindo um funcionamento ininterrupto, especialmente em dispositivos nos quais o método `isIncomingCallPermitted` pode gerar erros.

ConnectionService Unavailability Workaround

Em alguns dispositivos, como os smartphones Samsung no modo avião, o ConnectionService pode não estar disponível para o gerenciamento de chamadas efetuadas, o que pode causar problemas. Para resolver isso, apresentamos uma solução alternativa que permite fazer chamadas mesmo quando o ConnectionService não está disponível.

Workaround for Placing Outgoing Calls

Para contornar a indisponibilidade do ConnectionService, utilize o trecho de código a seguir em seu aplicativo para realizar chamadas de saída:

// Workaround for placing outgoing calls when ConnectionService is not available
private fun placeOutgoingCall(callId: CallId, callee: String) {
    try {
        coreContext.telecomHelper.startOutgoingCall(callId, callee)

        // If ConnectionService does not respond within 3 seconds,
        // we mock an outgoing connection
        TimerManager.startTimer(TimerManager.CONNECTION_SERVICE_TIMER, 3000) {
            mockOutgoingConnection(callId, callee)
        }
    } catch (e: Exception) {
        abortOutboundCall(callId, e.message)
    }
}

/**
 * This method will mock `ConnectionService#onCreateOutgoingConnection`,
 * allowing outgoing calls without direct interaction with the Telecom framework.
 */
private fun mockOutgoingConnection(callId: CallId, to: String): CallConnection {
    showToast(context, "ConnectionService Not Available")

    val connection = CallConnection(callId).apply {
        setAddress(Uri.parse(to), TelecomManager.PRESENTATION_ALLOWED)
        setCallerDisplayName(to, TelecomManager.PRESENTATION_ALLOWED)
        setDialing()
    }

    return connection
}

ConnectionService Implementation

Em seguida, certifique-se de que sua classe implemente os métodos necessários do ConnectionService, conforme mostrado abaixo:

import android.telecom.Connection
import android.telecom.ConnectionRequest
import android.telecom.PhoneAccountHandle
import android.telecom.ConnectionService
import android.telecom.TelecomManager

// Your class implementing ConnectionService
class YourConnectionService : ConnectionService() {

    override fun onCreateOutgoingConnection(
        connectionManagerPhoneAccount: PhoneAccountHandle?,
        request: ConnectionRequest?
    ): Connection {
        // Cancel the timer set in the workaround
        TimerManager.cancelTimer(TimerManager.CONNECTION_SERVICE_TIMER)

        // Your implementation of ConnectionService onCreateOutgoingConnection method
        // ... (code snippet)

        return connection
    }

    override fun onCreateOutgoingConnectionFailed(connectionManagerPhoneAccount: PhoneAccountHandle?, request: ConnectionRequest?) {
        // Cancel the timer set in the workaround
        TimerManager.cancelTimer(TimerManager.CONNECTION_SERVICE_TIMER)

        // Your implementation of ConnectionService onCreateOutgoingConnectionFailed method
        // ... (code snippet)
    }
}

TimerManager Utility

O TimerManager A classe utilizada na solução alternativa é apenas uma classe utilitária personalizada que permite definir um temporizador para uma função de retorno de chamada. Ela garante que a função seja executada caso o temporizador não seja cancelado antes do tempo especificado.

object TimerManager {
    private val handler: Handler = Handler(Looper.getMainLooper())
    private val timerMap: MutableMap<String, Runnable> = mutableMapOf()

    const val CONNECTION_SERVICE_TIMER = "ConnectionServiceTimer"

    fun startTimer(timerId: String, delayMillis: Long, callback: () -> Unit) {
        val runnable = Runnable {
            callback.invoke()
            timerMap.remove(timerId)
        }
        timerMap[timerId] = runnable
        handler.postDelayed(runnable, delayMillis)
    }

    fun cancelTimer(timerId: String) {
        val runnable = timerMap[timerId]
        if (runnable != null) {
            handler.removeCallbacks(runnable)
            timerMap.remove(timerId)
        }
    }
}

Ao incorporar essa solução alternativa e o utilitário TimerManager, seu aplicativo gerenciará com eficácia as chamadas efetuadas, mesmo em dispositivos nos quais o ConnectionService possa não funcionar corretamente.

Esta seção oferece uma visão geral concisa dos problemas conhecidos, específicos da plataforma e do dispositivo, que podem surgir ao integrar o Vonage Client SDK aos seus aplicativos para iOS.

Voice SDK Integration

Speakerphone Issues

Se você tiver problemas com o botão do viva-voz durante as chamadas, como falhas ou falta de resposta, verifique se não está interferindo no AVAudioSession.sharedInstance().

O Client SDK já cuida da sessão de áudio para você, então evitar manipulando-o diretamente com código como:

AVAudioSession.sharedInstance().setCategory(.playAndRecord)   

Fique tranquilo, pois o Client SDK se encarrega de gerenciar a sessão de áudio.

Para os usuários que utilizam o CallKit, continua sendo necessário chamar VGVoiceClient.enableAudio(audioSession) e VGVoiceClient.disableAudio(audioSession) com a `audioSession` fornecida pelos métodos delegados do CallKit.

Trabalhando com a CLI da Vonage

Configuração do aplicativo Vonage

Como é possível criar várias Applications do Vonage, os comandos executados referem-se à aplicação que foi configurada. Por exemplo, ao criar um usuário, é preciso certificar-se de criá-lo na aplicação pretendida.

  • Verifique a qual aplicativo sua CLI se refere executando:
cat vonage_app.json

Sem resposta aos comandos

Se você executar um comando e não receber uma resposta:

  • Tente verificar se todos os objetos JSON no seu comando estão corretamente fechados e se não há nenhum faltando } ou ' por exemplo.

JWTs

Lembre-se de que um JWT é válido por usuário e por Application da Vonage.

Erro de token inválido

  • Decodifique seu JWT

  • Certifique-se de que o "application_id" a afirmação está correta.

  • Certifique-se de que o "sub" está correto. Ou seja, existe um usuário com esse nome de usuário no seu aplicativo da Vonage.

  • Verifique se o JWT não expirou:

    • Você pode encontrar a data de validade em "exp", em tempo Unix, que corresponde aos segundos decorridos desde 1º de janeiro de 1970 (UTC).

    • Você pode convertê-lo para o tempo humano.

    • Certifique-se de que a data de validade seja futura, ou seja, que o JWT ainda não tenha expirado.

Erro de conexão ou tempo limite de conexão

Erro de conexão ou tempo limite de conexão ao tentar fazer login no SDK:

  • Verifique a conexão com a internet no seu dispositivo.

  • Então JWT pode estar em conformidade com os padrões do JWT; no entanto, a inclusão de algumas reivindicações pode estar incorreta de acordo com os requisitos da Vonage. Tente gerar um novo JWT, garantindo, ao mesmo tempo, a exatidão das suas alegações específicas relativas à Vonage.

Erros durante a geração de um JWT

  • Verifique se o arquivo da chave privada existe. Ele é gerado no computador em que você criou o aplicativo.

  • Em nossa documentação, ao usar a CLI, sugerimos utilizar o caminho ./private.key.

  • Certifique-se de que sua chave privada esteja na máquina em que você está gerando o JWT e que o caminho esteja correto.

  • Se você precisar de uma nova chave privada:

    • Você pode obter um no Painel de controle. No menu à esquerda, selecione Voz → Seus Applications → selecione o aplicativo → Editar. Na parte inferior, clique em Generate public / private key pair. Lembre-se de clicar em Save changes.

    • Salve o arquivo no seu computador e atualize o caminho para ele ao gerar o JWT.

Notificações push

  • Certifique-se de ter enviado o certificado para o servidor da Vonage. Você precisa ter um JWT de administrador válido, ou seja, um JWT sem o sub afirmação. Você pode Decodifique seu JWT para ter certeza.

  • Certifique-se de ter ativado as notificações push e de que o método client.registerVoipToken() foi bem-sucedida. Você também pode inserir uma chamada de log ou um ponto de interrupção para garantir que a chamada foi bem-sucedida.

Tem mais perguntas?

Caso tenha mais alguma dúvida, problema ou sugestão, entre em contato conosco pelo devrel@vonage.com ou o Slack da Comunidade de Desenvolvedores da Vonage.