
Criação de uma chamada de aplicativo para telefone usando Android e Flutter
Tempo de leitura: 11 minutos
Hoje vamos criar um aplicativo para Android usando Flutter e utilizaremos o Vonage Client SDK para fazer uma chamada de um aplicativo móvel para um telefone. O aplicativo terá três telas (três estados da interface do usuário):

Pré-requisitos
O código-fonte está disponível no GitHub.
Antes de começarmos a desenvolver o aplicativo para nosso dispositivo Android, você precisará cumprir os seguintes pré-requisitos:
Criar um objeto de controle de chamadas (NCCO)
Instale o CLI da Vonage
Configurar um aplicativo da Vonage
Instale o SDK do Flutter
Criar um projeto no Flutter
Aplicativo Vonage
Criar um NCCO
Um Objeto de Controle de Chamada (NCCO) é um array JSON que usamos para controlar o fluxo de uma chamada da Voice API. Mais informações sobre o NCCO podem ser encontradas aqui aqui.
O NCCO precisa ser público e acessível pela internet. Para isso, neste tutorial você utilizará o GitHub Gist , que oferece uma maneira prática de hospedar a configuração. Vamos adicionar um novo gist:
Acesse https://gist.github.com/ (você precisa estar conectado ao GitHub)
Crie um novo gist com
ncco.jsono nome de arquivoCopie e cole o seguinte objeto JSON no gist:
[
{
"action": "talk",
"text": "Please wait while we connect you."
},
{
"action": "connect",
"endpoint": [
{
"type": "phone",
"number": "PHONE_NUMBER"
}
]
}
]Substitua
PHONE_NUMBERpelo nosso número de telefone (os números da Vonage estão no formato E.164 https://developer.nexmo.com/concepts/guides/glossary#e-164-format; os caracteres '+' e '-' não são válidos. Certifique-se de especificar o código do país ao inserir o número; por exemplo, EUA: 14155550100 e Reino Unido: 447700900001)Clique no
Create secret gistbotãoClique no
RawbotãoAnote a URL exibida no nosso navegador; vamos usá-la na próxima etapa
Instalar o CLI do Vonage
O CLI da Vonage nos permite realizar diversas operações na linha de comando. Se quisermos realizar tarefas como criar Applications, adquirir Numbers da Vonage e assim por diante, precisaremos instalar a CLI da Vonage.
A CLI do Vonage requer node.js, portanto, precisaremos instalar o node.js primeiro, seguindo estas instruções.
Para instalar a versão Beta da CLI com o NPM, execute este comando:
npm install @vonage/cli -gConfigure a CLI da Vonage para usar nossa chave API e nosso segredo API da Vonage. Podemos obtê-los na página de configurações no Painel de Controle.
Execute o seguinte comando em um terminal, substituindo api_key e api_secret pelos nossos próprios:
vonage config:set --apiKey=api_key --apiSecret=api_secret Configurar o aplicativo Vonage
Crie o diretório do nosso projeto, caso ainda não tenha feito isso, executando o seguinte comando no terminal:
mkdir vonage-tutorial2. Navegue até o diretório do projeto:
cd vonage-tutorial3. Crie um aplicativo Vonage copiando e colando o comando abaixo no terminal. Certifique-se de alterar o valor do --voice-answer-url argumento, substituindo GIST-URL pela URL do gist da etapa anterior.
vonage apps:create "App to Phone Tutorial" --voice_event_url=https://example.com/ --voice_answer_url=GIST-URLAnote o ID do aplicativo que é exibido no terminal quando o aplicativo é criado.
NOTA: Um arquivo chamado
vonage_app.jsoné criado no diretório do nosso projeto e contém o ID do aplicativo Vonage recém-criado e a chave privada. Um arquivo de chave privada chamadoapp_to_phone_tutorial.keytambém é criado.
Criar usuário
Cada participante é representado por um objeto de usuário e deve ser autenticado pelo Client SDK. Em um aplicativo de produção, normalmente armazenaríamos essas informações do usuário em um banco de dados.
Execute o seguinte comando para criar um usuário chamado Alice
vonage apps:users:create Alice Gerar JWT
O JWT é usado para autenticar o usuário. Execute o seguinte comando no terminal para gerar um JWT para o usuário Alice.
No comando a seguir, substitua o APPLICATION_ID pelo ID do nosso aplicativo:
vonage jwt --app_id=APPLICATION_ID --subject=Alice --key_file=./app_to_phone_tutorial.key --acl='{
"paths": {
"/*/users/**": {},
"/*/conversations/**": {},
"/*/sessions/**": {},
"/*/devices/**": {},
"/*/image/**": {},
"/*/media/**": {},
"/*/push/**": {},
"/*/knocking/**": {},
"/*/legs/**": {}
}
}'O comando acima define a validade do JWT para um dia a partir de hoje, que é o prazo máximo.
Anote o JWT que geramos para Alice.
NOTA: Em um ambiente de produção, nosso aplicativo deve disponibilizar um endpoint que gere um JWT para cada solicitação do cliente.
Instalar o Android Studio
Baixe e instale o Android Studio.
Configuração do Flutter
Instalar o SDK do Flutter
Essa etapa varia entre o macOS, o Windows e o Linux, mas, em geral, resume-se a baixar o SDK do Flutter para o sistema operacional em questão, extrair o arquivo do SDK e adicionar a sdk\bin pasta à variável PATH do sistema. Instruções detalhadas podem ser encontradas aqui.
Felizmente, o Flutter vem com uma ferramenta que nos permite verificar se o SDK e todos os “componentes” necessários estão presentes e configurados corretamente. Execute este comando:
flutter doctorO Flutter Doctor Verifyará se o SDK do Flutter está instalado e se os demais componentes estão instalados e configurados corretamente. Caso sejam detectados problemas, veremos a descrição e uma sugestão sobre como corrigi-los.
Instale o plugin do Flutter
Abrir o Android Studio, vá até Preferences | plugins e instale os plug-ins do Flutter e do Dart a partir do marketplace.
O plugin do Flutter adicionará uma nova barra de ferramentas que permite executar e depurar aplicativos Flutter:

Criar o projeto Flutter
Você criará um projeto Flutter usando o Android Studio.
Executar o Android Studio
Na tela de boas-vindas do Android Studio, selecione
Create New Flutter project

Selecione
Flutter Applicatione cliqueNextDigite
app_to_phone_fluttercomo nome do projeto, digiteFlutter SDK pathe clique emNextSelecione
Include Kotlin support for Android codee cliqueFinish
Observe que
app_to_phone_flutteressa pasta (projeto Flutter) contémiosuma pasta contendo o projeto do sistema operacional eiosuma pasta contendo o projeto para iOS.
Conecte o dispositivo Android ou o emulador e execute o aplicativo para verificar se tudo funciona conforme o esperado.
Comunicação bidirecional entre o Flutter e o Android
No momento, o Client SDK não está disponível como um pacote do Flutter; portanto, teremos que usar o Client SDK do Cliente nativo do Android e nos comunicarmos entre o Android e o Flutter usando o MethodChannel — dessa forma, o Flutter chamará métodos do Android, e o Android chamará métodos do Flutter.
O código do Flutter será armazenado no lib/ain.dart arquivo, enquanto o código nativo do Android será armazenado no android/app/src/main/kotlin/com/example/app_to_phone_flutter/MainActivity.kt arquivo.
Inicializar o aplicativo Flutter
Os aplicativos Flutter são desenvolvidos usando uma linguagem de programação chamada Dart.
Abra lib/main.dart arquivo e substitua todo o conteúdo pelo código a seguir:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: CallWidget(title: 'app-to-phone-flutter'),
);
}
}
class CallWidget extends StatefulWidget {
CallWidget({Key key, this.title}) : super(key: key);
final String title;
@override
_CallWidgetState createState() => _CallWidgetState();
}
class _CallWidgetState extends State<CallWidget> {
SdkState _sdkState = SdkState.LOGGED_OUT;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 64),
_updateView()
],
),
),
);
}
Widget _updateView() {
if (_sdkState == SdkState.LOGGED_OUT) {
return ElevatedButton(
child: Text("LOGIN AS ALICE")
);
}
}
Future<void> _loginUser() async {
// Login user
}
Future<void> _makeCall() async {
// Make call
}
Future<void> _endCall() async {
// End call
}
}
enum SdkState {
LOGGED_OUT,
LOGGED_IN,
WAIT,
ON_CALL,
ERROR
}O código acima contém CallWidget que será responsável por gerenciar o estado do aplicativo (fazer o login do usuário e gerenciar a chamada). A SdkState enum representa os possíveis estados do Vonage Client SDK. Essa enum será definida duas vezes — uma para o Flutter usando Dart e outra para o Android usando Kotlin. O widget contém o _updateView método que alterará a interface do usuário com base no SdkState valor.
Execute o aplicativo usando o botão com a seta verde na barra de ferramentas do Flutter:

Devemos ver o Login Alice botão:

Tela de login
O Login as Aice botão está desativado; agora adicione onPressed um manipulador ao ElevatedButton para permitir o login:
Widget _updateView() {
if (_sdkState == SdkState.LOGGED_OUT) {
return ElevatedButton(
onPressed: () { _loginUser(); },
child: Text("LOGIN AS ALICE")
);
}
}Atualizar o corpo do _loginUser método para se comunicar com o código nativo e fazer o login do usuário:
Future<void> _loginUser() async {
String token = "ALICE_TOKEN";
try {
await platformMethodChannel.invokeMethod('loginUser', <String, dynamic>{'token': token});
} on PlatformException catch (e) {
print(e);
}
}Substitua o ALICE_TOKEN pelo token JWT que obtivemos anteriormente para autenticar o usuário Alice pela CLI da Vonage. O Flutter chamará loginUser método e passará o token como argumento. O loginUser método definido na MainActivity classe (você chegará lá em um instante). Para chamar esse método a partir do Flutter, precisamos definir um MethodChannel. Adicione o platformMethodChannel campo no topo da _CallWidgetState classe:
class _CallWidgetState extends State<CallWidget> {
SdkState _sdkState = SdkState.LOGGED_OUT;
static const platformMethodChannel = const MethodChannel('com.vonage');A com.vonage string representa o ID exclusivo do canal, ao qual também faremos referência no código nativo do Android (MainActivity classe). Agora precisamos processar essa chamada de método no lado nativo do Android.
Abrir MainActivity classe. Observe que o plug-in do Flutter exibe uma sugestão para abrir esse projeto Android em uma instância separada do Android Studio (outra janela). Faça isso para ter um preenchimento automático de código melhor para o projeto Android:

NOTA: Isso ocorre porque o projeto Flutter é composto pelo projeto para Android e pelo projeto para iOS.
Para detectar chamadas de método originadas do Flutter, sobrescreva configureFlutterEngine e adicionar addFlutterChannelListener a chamada de método dentro do configureFlutterEngine método:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
addFlutterChannelListener()
}Agora adicione addFlutterChannelListener e loginUser métodos dentro da MainActivity classe (no mesmo nível que o configureFlutterEngine ):
private fun addFlutterChannelListener() {
MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
when (call.method) {
"loginUser" -> {
val token = requireNotNull(call.argument<String>("token"))
loginUser(token)
result.success("")
}
else -> {
result.notImplemented()
}
}
}
}
private fun loginUser(token: String) {
Log.d("TAG", "login with token: $token")
}Depois de executar o aplicativo, devemos ver login with token... essa mensagem no Logcat do Android. Agora é hora de criar um client.
Adicionar dependência do Client SDK
Adicione um repositório Maven com URL personalizada à nossa configuração do Gradle. Adicione o seguinte bloco maven dentro do allprojects bloco dentro do arquivo build.gradle.kts :
allprojects {
repositories {
google()
jcenter()
maven {
url "https://artifactory.ess-dev.com/artifactory/gradle-dev-local"
}
}
}Agora adicione a dependência do Client SDK ao projeto no app\build.gradle arquivo:
dependencies {
// ...
implementation 'com.nexmo.android:client-sdk:2.8.1'
}Nesse mesmo arquivo, defina a versão mínima do Android SDK como 23:
minSdkVersion 23Execute Sync project with Gradle no Android Studio, conforme mostrado no exemplo abaixo:

Inicializar o cliente
Abra MainActivity classe e adicione a client propriedade que conterá a referência ao cliente Nexmo:
private lateinit var client: NexmoClientAgora adicione initClient o método para inicializar o cliente:
private fun initClient() {
client = NexmoClient.Builder().build(this)
}Para chamar o initClient método a partir do configureFlutterEngine , precisaremos adicionar a initClient() linha conforme mostrado no exemplo abaixo:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
initClient()
addFlutterChannelListener()
} Fazer login como usuário
Modificar login o corpo do método para chamar login na instância do cliente:
private fun login(token: String) {
client.login(token)
}Isso nos permitirá fazer o login do usuário (Alice) usando o Client SDK.
Notificar o Flutter sobre a alteração no estado do Client SDK
Para notificar o Flutter sobre quaisquer alterações no estado do SDK, você precisará adicionar enum para representar os estados do Client SDK. Você já adicionou a enumeração equivalente SdkState enum no main.dart arquivo). Adicione a seguinteSdkState enum, no final do MainActivity.kt arquivo:
enum class SdkState {
LOGGED_OUT,
LOGGED_IN,
WAIT,
ON_CALL,
ERROR
}Em seguida, precisamos adicionar o ouvinte de conexão e mapear alguns dos estados do SDK para a SdkState enumeração. Modifique o corpo do initClient método conforme mostrado no exemplo abaixo:
private fun initClient() {
client = NexmoClient.Builder().build(this)
client.setConnectionListener { connectionStatus, _ ->
when (connectionStatus) {
ConnectionStatus.CONNECTED -> notifyFlutter(SdkState.LOGGED_IN)
ConnectionStatus.DISCONNECTED -> notifyFlutter(SdkState.LOGGED_OUT)
ConnectionStatus.CONNECTING -> notifyFlutter(SdkState.WAIT)
ConnectionStatus.UNKNOWN -> notifyFlutter(SdkState.ERROR)
}
}
}Por fim, o notifyFlutter método precisa ser adicionado à MainActivity classe:
private fun notifyFlutter(state: SdkState) {
Handler(Looper.getMainLooper()).post {
MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, "com.vonage")
.invokeMethod("updateState", state.toString())
}
}Observe que armazenamos o estado na enumeração, mas o estamos enviando como uma string. A comunicação com o Flutter ocorre no main thread, por isso precisamos usar Handler para alternar entre threads. O MethodChannel chamará updateState método definido no main.dart arquivo.
Recuperar o estado do SDK usando o Flutter
Para recuperar atualizações de estado no Flutter, precisamos monitorar as atualizações do canal de métodos. Abra main.dart arquivo e adicione esses dois métodos dentro da _CallWidgetState classe:
_CallWidgetState() {
platformMethodChannel.setMethodCallHandler(methodCallHandler);
}
Future<dynamic> methodCallHandler(MethodCall methodCall) async {
switch (methodCall.method) {
case 'updateState':
{
setState(() {
var arguments = 'SdkState.${methodCall.arguments}';
_sdkState = SdkState.values.firstWhere((v) {return v.toString() == arguments;}
);
});
}
break;
default:
throw MissingPluginException('notImplemented');
}
}Esses métodos recebem o “sinal” do Android e o convertem em uma enumeração. Agora, atualize o conteúdo do _updateView método para oferecer suporte SdkState.WAIT e SdkState.LOGGED_IN estados, conforme mostrado no exemplo abaixo:
Widget _updateView() {
if (_sdkState == SdkState.LOGGED_OUT) {
return ElevatedButton(
onPressed: () { _loginUser(); },
child: Text("LOGIN AS ALICE")
);
} else if (_sdkState == SdkState.WAIT) {
return Center(
child: CircularProgressIndicator(),
);
} else if (_sdkState == SdkState.LOGGED_IN) {
return ElevatedButton(
onPressed: () { _makeCall(); },
child: Text("MAKE PHONE CALL")
);
}
}Durante SdkState.WAIT a barra de progresso será exibida. Após o login bem-sucedido, o aplicativo exibirá o MAKE PHONE CALL botão.
NOTA: Ao modificar o código nativo do Android, o recurso de recarga dinâmica do Flutter não funcionará. É preciso encerrar o aplicativo e executá-lo novamente.
Execute o aplicativo e clique no botão com a legenda LOGIN AS ALICE. O MAKE PHONE CALL deve aparecer o botão, que é outro estado do aplicativo Flutter com base na SdkState enum`). Um exemplo disso é mostrado na imagem abaixo:

Faça uma ligação
Agora precisamos adicionar a funcionalidade para fazer uma ligação telefônica. Abra o main.dart arquivo e atualize o corpo do _makeCall método conforme mostrado abaixo:
Future<void> _makeCall() async {
try {
await requestPermissions();
await platformMethodChannel
.invokeMethod('makeCall');
} on PlatformException catch (e) {
print(e);
}
}O método acima se comunicará com o Android, portanto, precisamos atualizar o código na MainActivity classe também. Adicione makeCall cláusulas à when instrução dentro do addFlutterChannelListener método:
private fun addFlutterChannelListener() {
MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, "com.vonage").setMethodCallHandler { call, result ->
when (call.method) {
"loginUser" -> {
val token = requireNotNull(call.argument<String>("token"))
login(token)
result.success("")
}
"makeCall" -> {
makeCall()
result.success("")
}
else -> {
result.notImplemented()
}
}
}
}Agora, no mesmo arquivo, adicione a onGoingCall propriedade, que define se e quando uma chamada está em andamento:
private var onGoingCall: NexmoCall? = nullNOTA: Atualmente, o Client SDK não armazena a referência da chamada em andamento; portanto, precisamos armazená-la na
MainActivityclasse. Vamos usá-la mais tarde para encerrar a chamada.
Agora, no mesmo arquivo, adicione makeCall o método:
@SuppressLint("MissingPermission")
private fun makeCall() {
notifyFlutter(SdkState.WAIT)
// Callee number is ignored because it is specified in NCCO config
client.call("IGNORED_NUMBER", NexmoCallHandler.SERVER, object : NexmoRequestListener<NexmoCall> {
override fun onSuccess(call: NexmoCall?) {
onGoingCall = call
notifyFlutter(SdkState.ON_CALL)
}
override fun onError(apiError: NexmoApiError) {
notifyFlutter(SdkState.ERROR)
}
})
}O método acima define o estado do aplicativo Flutter como SdkState.WAIT e aguarda a resposta do Client SDK (erro ou sucesso). Agora precisamos adicionar suporte para ambos os estados (SdkState.ON_CALL e SdkState.ERROR) dentro do main.dart arquivo (Flutter). Atualize o corpo do _updateView método para que fique igual ao exemplo abaixo:
Widget _updateView() {
if (_sdkState == SdkState.LOGGED_OUT) {
return ElevatedButton(
onPressed: () { _loginUser(); },
child: Text("LOGIN AS ALICE")
);
} else if (_sdkState == SdkState.WAIT) {
return Center(
child: CircularProgressIndicator(),
);
} else if (_sdkState == SdkState.LOGGED_IN) {
return ElevatedButton(
onPressed: () { _makeCall(); },
child: Text("MAKE PHONE CALL")
);
} else if (_sdkState == SdkState.ON_CALL) {
return ElevatedButton(
onPressed: () { _endCall(); },
child: Text("END CALL")
);
} else {
return Center(
child: Text("ERROR")
);
}
}Cada mudança de estado resultará em uma modificação na interface do usuário. Antes de fazer uma chamada, o aplicativo precisa de permissões específicas para usar o microfone. Na próxima etapa, vamos adicionar ao nosso projeto a funcionalidade para solicitar essas permissões.
Solicitar permissões
O aplicativo precisa ter acesso ao microfone, por isso precisamos solicitar a android.permission.RECORD_AUDIO (o Flutter chama isso de Permission.microphone).
Primeiro, precisamos adicionar o permission_handler . Abra o pubspec.yaml arquivo e adicione permission_handler: ^6.0.1+1 dependência em sdk: flutter:
dependencies:
flutter:
sdk: flutter
permission_handler: ^6.0.1+1A indentação é importante nos
yamlarquivos; portanto, certifique-se de quepermission_handlereste esteja no mesmo nível de recuo que oflutter:item.
Execute o comando abaixo no terminal para baixar o pacote Flutter recém-adicionado:
flutter pub getNo início do main.dart arquivo, você precisará importar o permission_handler pacote, conforme mostrado no exemplo abaixo:
import 'package:permission_handler/permission_handler.dart';Para acionar a solicitação de determinadas permissões, você precisará adicionar o requestPermissions() método dentro da _CallWidgetState classe dentro do main.dart arquivo. Portanto, adicione este novo método dentro da classe:
Future<void> requestPermissions() async {
await [ Permission.microphone].request();
}Por fim, precisamos adicionar duas permissões (uses-permission tags) dentro do app/src/main/AndroidManifest.xml arquivo, acima da application tag:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
...NOTA:
android.permission.INTERNETa permissão é concedida implicitamente pelo Android, portanto, não precisamos solicitá-la explicitamente no Flutter.
Execute o aplicativo e clique em MAKE PHONE CALL para iniciar uma chamada. A janela de permissão será exibida e, após conceder as permissões, a chamada será iniciada.
Observação: definimos o número de telefone anteriormente no NCCO
O status do aplicativo será atualizado para SdkState.ON_CALL e a interface do usuário será atualizada:

Encerrar a chamada
Para encerrar a chamada, precisamos acionar o método no aplicativo nativo do Android usando platformMethodChannel. Dentro do main.dart corpo do arquivo de atualização do _endCall método:
Future<void> _endCall() async {
try {
await platformMethodChannel.invokeMethod('endCall');
} on PlatformException catch (e) {}
}O método acima se comunicará com o Android, portanto, precisamos atualizar o código na MainActivity classe. Adicione endCall cláusulas à when instrução dentro do addFlutterChannelListener método:
when (call.method) {
"loginUser" -> {
val token = requireNotNull(call.argument<String>("token"))
login(token)
result.success("")
}
"makeCall" -> {
makeCall()
result.success("")
}
"endCall" -> {
endCall()
result.success("")
}
else -> {
result.notImplemented()
}
}Agora, no mesmo arquivo, adicione o endCall método:
private fun endCall() {
onGoingCall?.hangup(object : NexmoRequestListener<NexmoCall> {
override fun onSuccess(call: NexmoCall?) {
onGoingCall = null
notifyFlutter(SdkState.LOGGED_IN)
}
override fun onError(apiError: NexmoApiError) {
notifyFlutter(SdkState.ERROR)
}
})
}O método acima define o estado do aplicativo Flutter como SdkState.WAIT e aguarda a resposta do Client SDK, que pode ser de erro ou sucesso. Ambos os estados da interface do usuário já são suportados no aplicativo Flutter.
Você tratou do encerramento da chamada pressionando END CALL botão na interface do usuário do aplicativo Flutter; no entanto, a chamada também pode ser encerrada fora do aplicativo Flutter — por exemplo, a chamada pode ser rejeitada ou atendida e, posteriormente, encerrada pelo destinatário (no telefone real).
Para dar suporte a esses casos, precisamos adicionar NexmoCallEventListener um ouvinte à instância da chamada e ficar atento aos eventos específicos da chamada.
Defina a callEventListener propriedade no início da MainActivity classe:
private val callEventListener = object : NexmoCallEventListener {
override fun onMemberStatusUpdated(callMemberStatus: NexmoCallMemberStatus, callMember: NexmoCallMember) {
if (callMemberStatus == NexmoCallMemberStatus.COMPLETED || callMemberStatus == NexmoCallMemberStatus.CANCELLED) {
onGoingCall = null
}
}
override fun onMuteChanged(mediaActionState: NexmoMediaActionState, callMember: NexmoCallMember) {}
override fun onEarmuffChanged(mediaActionState: NexmoMediaActionState, callMember: NexmoCallMember) {}
override fun onDTMF(dtmf: String, callMember: NexmoCallMember) {}
}A onMemberStatusUpdated callback nos informa que a chamada foi encerrada.
Para registrar o ouvinte acima, modifique onSuccess o callback dentro do makeCall método:
onGoingCall = call
onGoingCall?.addCallEventListener(callEventListener)Por fim, modifique endCall o método para cancelar o registro do callEventListener ouvinte dentro do onSuccess callback:
onGoingCall?.removeCallEventListener(callEventListener)
onGoingCall = nullExecute o aplicativo e, se você seguiu este tutorial passo a passo, poderá fazer uma ligação do nosso aplicativo móvel para um número de telefone fixo.
Resumo
Você criou o aplicativo com sucesso. Com isso, aprendemos como fazer uma ligação de um aplicativo móvel para um telefone usando o Vonage Client SDK. Para ver a versão completa, consulte este projeto no GitHub.
Para se familiarizar com outros casos de uso, consulte outros tutoriais e o Centro de Desenvolvedores da Vonage.