
Creación de una llamada de aplicación a teléfono con Android y Flutter
Tiempo de lectura: 12 minutos
Hoy vamos a crear una aplicación para Android utilizando Flutter y utilizaremos Vonage Client SDK para realizar una llamada desde una aplicación móvil al teléfono. La aplicación tendrá 3 pantallas (3 estados de UI):

Requisitos previos
El código fuente está disponible en GitHub.
Antes de empezar a crear la aplicación para nuestro dispositivo Android, tendrás que prepararte con los siguientes requisitos previos:
Crear un objeto de control de llamada (OCNC)
Instalar la CLI de Vonage
Configurar una aplicación de Vonage
Instalar el SDK de Flutter
Crear un proyecto Flutter
Aplicación de Vonage
Crear una OCN
Un objeto de control de llamada (NCCO) es una matriz JSON que utilizamos para controlar el flujo de una llamada Voice API. Puede encontrar más información sobre NCCO aquí.
La OCN tiene que ser pública y accesible por Internet. Para conseguirlo, en este tutorial utilizarás GitHub Gist que proporciona una forma conveniente de alojar la configuración. Vamos a añadir un nuevo gist:
Ir a https://gist.github.com/ (tienes que haber iniciado sesión en Github)
Crear un nuevo gist con
ncco.jsoncomo nombre de archivoCopia y pega el siguiente objeto JSON en el gist:
[
{
"action": "talk",
"text": "Please wait while we connect you."
},
{
"action": "connect",
"endpoint": [
{
"type": "phone",
"number": "PHONE_NUMBER"
}
]
}
]Sustituye
PHONE_NUMBERpor nuestro número de teléfono (los números de Vonage están en formato E.164 https://developer.nexmo.com/concepts/guides/glossary#e-164-formatlos signos '+' y '-' no son válidos. Asegúrese de especificar nuestro código de país al introducir nuestro número, por ejemplo, US: 14155550100 y UK: 447700900001)Haga clic en el botón
Create secret gistbotónHaga clic en el botón
RawbotónToma nota de la URL que aparece en nuestro navegador, la utilizaremos en el siguiente paso
Instalar Vonage CLI
El CLI de Vonage nos permite realizar muchas operaciones en la línea de comandos. Si queremos realizar tareas como crear aplicaciones, comprar números de Vonage, etc., necesitaremos instalar la CLI de Vonage.
Vonage CLI requiere node.jspor lo que necesitaremos instalar node.js primero usando estas instrucciones.
Para instalar la versión Beta del CLI con NPM ejecuta este comando:
npm install @vonage/cli -gConfigure la CLI de Vonage para utilizar la clave y el secreto de la API de Vonage. página de configuración en el panel.
Ejecuta el siguiente comando en un terminal, sustituyendo api_key y api_secret por los nuestros:
vonage config:set --apiKey=api_key --apiSecret=api_secret Configurar aplicación de Vonage
Crear nuestro directorio de proyecto si aún no lo ha hecho, ejecute el siguiente comando en nuestro terminal:
mkdir vonage-tutorial2. Cambie al directorio del proyecto:
cd vonage-tutorial3. Crea una aplicación de Vonage copiando y pegando el siguiente comando en el terminal Asegúrate de cambiar el valor de --voice-answer-url sustituyendo GIST-URL por la URL gist del paso anterior.
vonage apps:create "App to Phone Tutorial" --voice_event_url=https://example.com/ --voice_answer_url=GIST-URLAnote el ID de la aplicación que aparece en nuestro terminal cuando se crea nuestra aplicación.
NOTA: se crea un archivo llamado
vonage_app.jsonen el directorio de nuestro proyecto y contiene el nuevo ID de aplicación de Vonage y la clave privada. También se crea un archivo de clave privada llamadoapp_to_phone_tutorial.keytambién se crea.
Crear usuario
Cada participante está representado por un Usuario y debe ser autenticado por el Client SDK. En una aplicación de producción, normalmente almacenaríamos esta información de usuario en una base de datos.
Ejecute el siguiente comando para crear un usuario llamado Alice
vonage apps:users:create Alice Generar JWT
El JWT se utiliza para autenticar al usuario. Ejecute el siguiente comando en el terminal para generar un JWT para el usuario Alice.
En el siguiente comando sustituya el APPLICATION_ID por el ID de nuestra aplicación:
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/**": {}
}
}'El comando anterior establece la caducidad del JWT en un día a partir de ahora, que es el máximo.
Anote el JWT que generamos para Alice.
NOTA: En un entorno de producción, nuestra aplicación debe exponer un endpoint que genere un JWT para cada petición del cliente.
Instalar Android Studio
Descargar e instalar Android Studio.
Configuración de Flutter
Instalar el SDK de Flutter
Este paso variará en MacOS, Win y Linux, pero en general, se reduce a descargar el SDK de flutter para un sistema operativo determinado, extraer el archivo SDK y añadir la carpeta sdk\bin a la variable PATH del sistema. Encontrará instrucciones detalladas aquí.
Afortunadamente, flutter viene con una herramienta que nos permite verificar si el SDK y todos los "componentes" requeridos están presentes y configurados correctamente. Ejecute este comando:
flutter doctorFlutter Doctor verificará si Flutter SDK está instalado y otros componentes están instalados y configurados correctamente. Si se detectan problemas, veremos la descripción y una sugerencia para solucionarlos.
Instalar el plugin Flutter
Abrir Android Studiovaya a Preferences | plugins e instala los plugins Flutter y Dart desde el marketplace.
El plugin Flutter añadirá una nueva barra de herramientas que permite ejecutar y depurar la aplicación Flutter:

Crear el proyecto Flutter
Creará un proyecto Flutter utilizando Android Studio.
Ejecutar Android Studio
En la pantalla de bienvenida de Android Studio seleccione
Create New Flutter project

Seleccione
Flutter Applicationy haga clic enNextIntroduzca
app_to_phone_fluttercomo nombre del proyecto, introduzcaFlutter SDK pathy haga clic enNextSeleccione
Include Kotlin support for Android codey haga clic enFinish
Tenga en cuenta que
app_to_phone_flutter(proyecto flutter) contieneiosque contiene el proyecto OS yiosque contiene el proyecto iOS.
Conecta el dispositivo Android o el emulador y ejecuta la aplicación para verificar que todo funciona como se espera.
Comunicación bidireccional Flutter/Android
Actualmente, Client SDK no está disponible como un paquete de Flutter, por lo que tendremos que utilizar Client SDK nativo de Android y comunicarnos entre Android y Flutter utilizando MethodChannel - de esta forma, Flutter llamará a los métodos de Android, y Android llamará a los métodos de Flutter.
El código de Flutter se almacenará en el archivo lib/ain.dart mientras que el código nativo de Android se almacenará en el archivo android/app/src/main/kotlin/com/example/app_to_phone_flutter/MainActivity.kt archivo.
Aplicación Init Flutter
Las Applications de Flutter se construyen utilizando un lenguaje de programación llamado Dart.
Abra el archivo lib/main.dart y sustituya todo el contenido por el siguiente código:
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
}El código anterior contiene custom CallWidget que se encargará de gestionar el estado de la aplicación (registro del usuario y gestión de la llamada). El enum SdkState representa los posibles estados de Vonage Client SDK. Este enum será definido dos veces - uno para Flutter usando Dart y otro para Android usando Kotlin. El widget contiene el método _updateView que cambiará la interfaz de usuario en función del valor SdkState el valor.
Ejecute la aplicación con el botón de flecha verde de la barra de herramientas de Flutter:

Deberíamos ver el botón Login Alice botón

Pantalla de inicio de sesión
El botón Login as Aice está desactivado, así que ahora añade onPressed al botón ElevatedButton para permitir el inicio de sesión:
Widget _updateView() {
if (_sdkState == SdkState.LOGGED_OUT) {
return ElevatedButton(
onPressed: () { _loginUser(); },
child: Text("LOGIN AS ALICE")
);
}
}Actualizar el cuerpo de _loginUser para comunicarse con el código nativo y acceder al usuario:
Future<void> _loginUser() async {
String token = "ALICE_TOKEN";
try {
await platformMethodChannel.invokeMethod('loginUser', <String, dynamic>{'token': token});
} on PlatformException catch (e) {
print(e);
}
}Sustituye el ALICE_TOKEN con el token JWT, que obtuvimos anteriormente, para autenticar al usuario Alice desde la CLI de Vonage. Flutter llamará al método loginUser y pasará el token como argumento. El método loginUser definido en la clase MainActivity (lo verás en un momento). Para llamar a este método desde Flutter tenemos que definir un método MethodChannel. Añade el campo platformMethodChannel en la parte superior de _CallWidgetState la clase:
class _CallWidgetState extends State<CallWidget> {
SdkState _sdkState = SdkState.LOGGED_OUT;
static const platformMethodChannel = const MethodChannel('com.vonage');La cadena com.vonage string representa el identificador único del canal que también referenciaremos en el código nativo de Android (MainActivity class). Ahora tenemos que manejar esta llamada de método en el lado nativo de Android.
Abra MainActivity clase. Tenga en cuenta que el plugin Flutter muestra una sugerencia para abrir este proyecto Android en una instancia separada de Android Studio (otra ventana). Hágalo para tener una mejor finalización de código para el proyecto Android:

NOTA: Esto ocurre porque el proyecto Flutter está formado por el proyecto Android y el proyecto iOS.
Para escuchar las llamadas a métodos originadas en Flutter sobreescribe configureFlutterEngine y añadir addFlutterChannelListener llamada de método dentro de configureFlutterEngine método:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
addFlutterChannelListener()
}Ahora añade addFlutterChannelListener y loginUser dentro de la clase MainActivity (al mismo nivel que el método configureFlutterEngine anterior):
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")
}Después de ejecutar la aplicación deberíamos ver login with token... en Android Logcat. Ahora es el momento de crear un client.
Añadir dependencia de Client SDK
Añade un repositorio Maven URL personalizado a nuestra configuración de Gradle. Añade el siguiente bloque maven dentro del bloque allprojects dentro del archivo build.gradle.kts del proyecto:
allprojects {
repositories {
google()
jcenter()
maven {
url "https://artifactory.ess-dev.com/artifactory/gradle-dev-local"
}
}
}Ahora añada la dependencia Client SDK al proyecto en el archivo app\build.gradle archivo:
dependencies {
// ...
implementation 'com.nexmo.android:client-sdk:2.8.1'
}En el mismo archivo establece min versión de Android SDK a 23:
minSdkVersion 23Ejecute el comando Sync project with Gradle en Android Studio, como se muestra en el siguiente ejemplo:

Inicializar cliente
Abra la clase MainActivity y añada la propiedad client que contendrá la referencia al cliente Nexmo:
private lateinit var client: NexmoClientAhora añade el método initClient para inicializar el cliente:
private fun initClient() {
client = NexmoClient.Builder().build(this)
}Para llamar al método initClient desde el método configureFlutterEngine existente, tendremos que añadir la línea initClient() como se muestra en el siguiente ejemplo:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
initClient()
addFlutterChannelListener()
} Iniciar sesión El usuario
Modificar login el cuerpo del método para llamar login en la instancia del cliente:
private fun login(token: String) {
client.login(token)
}Esto nos permitirá registrar al usuario (Alice) utilizando Client SDK.
Notificación a Flutter del cambio de estado del Client SDK
Para notificar a Flutter cualquier cambio en el estado del SDK, tendrás que añadir enum para representar los estados del Client SDK. Ya has añadido el equivalente SdkState enum en el archivo main.dart archivo). Añade el siguienteSdkState enum, al final del MainActivity.kt archivo:
enum class SdkState {
LOGGED_OUT,
LOGGED_IN,
WAIT,
ON_CALL,
ERROR
}A continuación, tenemos que añadir el listener de conexión y mapear algunos de los estados del SDK a SdkState enum. Modifica el cuerpo del método initClient como se muestra en el siguiente ejemplo:
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 último, el método notifyFlutter a la clase MainActivity clase:
private fun notifyFlutter(state: SdkState) {
Handler(Looper.getMainLooper()).post {
MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, "com.vonage")
.invokeMethod("updateState", state.toString())
}
}Observa que almacenamos el estado en el enum, pero lo estamos enviando como una cadena. La comunicación con Flutter se produce en el main por lo que necesitamos usar Handler para cambiar de hilo. El MethodChannel llamará al método updateState definido en el archivo main.dart archivo.
Recuperar el estado del SDK por Flutter
Para recuperar las actualizaciones de estado en Flutter tenemos que escuchar las actualizaciones del canal de métodos. Abra el archivo main.dart y añade estos dos métodos dentro de _CallWidgetState de la clase:
_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');
}
}Estos métodos reciben la "señal" de Android y la convierte en un enum. Ahora actualiza el contenido del método _updateView para que admita SdkState.WAIT y SdkState.LOGGED_IN states, como se muestra en el siguiente ejemplo:
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 se mostrará la barra de progreso. Después de iniciar sesión con éxito, la aplicación mostrará el botón MAKE PHONE CALL botón .
NOTA: Al modificar el código nativo de Android Flutter hot reload no funcionará. tenemos que detener la aplicación y ejecutarla de nuevo.
Ejecute la aplicación y haga clic en el botón LOGIN AS ALICE. Debería aparecer el botón MAKE PHONE CALL que es otro estado de la aplicación Flutter basado en la función SdkState enum`). En la siguiente imagen se muestra un ejemplo:

Hacer una llamada
Ahora tenemos que añadir la funcionalidad para hacer una llamada telefónica. Abre el archivo main.dart y actualiza el cuerpo del método _makeCall como se muestra a continuación:
Future<void> _makeCall() async {
try {
await requestPermissions();
await platformMethodChannel
.invokeMethod('makeCall');
} on PlatformException catch (e) {
print(e);
}
}El método anterior se comunicará con Android por lo que tenemos que actualizar el código en MainActivity también. Añadir makeCall a la sentencia when dentro del método addFlutterChannelListener del 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()
}
}
}
}Ahora, en el mismo archivo, añada la propiedad onGoingCall que define si una llamada está en curso y cuándo:
private var onGoingCall: NexmoCall? = nullNOTA: Actualmente el Client SDK no almacena la referencia de la llamada en curso, por lo que tenemos que almacenarla en la clase
MainActivityque utilizaremos más adelante para finalizar la llamada.
Ahora en el mismo archivo añade makeCall 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)
}
})
}El método anterior establece el estado de la aplicación Flutter en SdkState.WAIT y espera la respuesta del Client SDK (error o éxito). Ahora tenemos que añadir soporte para ambos estados (SdkState.ON_CALL y SdkState.ERROR) dentro del archivo main.dart (Flutter). Actualizar el cuerpo del método _updateView para que muestre lo mismo que a continuación:
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 cambio de estado dará lugar a una modificación de la interfaz de usuario. Antes de realizar una llamada, la aplicación necesita permisos específicos para utilizar el micrófono. En el siguiente paso, vamos a añadir la funcionalidad en nuestro proyecto para solicitar estos permisos.
Solicitar permisos
La aplicación necesita poder acceder al micrófono, por lo que tenemos que solicitar el permiso de Android android.permission.RECORD_AUDIO (Flutter lo llama Permission.microphone).
En primer lugar, tenemos que añadir el permission_handler paquete. Abra el archivo pubspec.yaml y añade la dependencia permission_handler: ^6.0.1+1 dependencia bajo sdk: flutter:
dependencies:
flutter:
sdk: flutter
permission_handler: ^6.0.1+1La sangría es importante en los archivos
yamlasí que asegúrese de quepermission_handleresté en el mismo nivel de sangría que el elementoflutter:elemento.
Ejecute el siguiente comando en el terminal para descargar el paquete Flutter recién añadido:
flutter pub getEn la parte superior del archivo main.dart deberá importar el paquete permission_handler como se muestra en el siguiente ejemplo:
import 'package:permission_handler/permission_handler.dart';Para activar la solicitud de determinados permisos, tendrá que añadir el método requestPermissions() dentro de la clase _CallWidgetState dentro del archivo main.dart archivo. Así que añade este nuevo método dentro de la clase:
Future<void> requestPermissions() async {
await [ Permission.microphone].request();
}Por último, tenemos que añadir dos permisos (uses-permission tags) dentro del archivo app/src/main/AndroidManifest.xml encima de la etiqueta application tag:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
...NOTA:
android.permission.INTERNETel permiso lo concede implícitamente Android, por lo que no tenemos que solicitarlo en Flutter explícitamente.
Ejecute la aplicación y pulse MAKE PHONE CALL para iniciar una llamada. Aparecerá el cuadro de diálogo de permisos y, una vez concedidos, se iniciará la llamada.
Resto: hemos definido el número de teléfono anteriormente en NCCO
El estado de la aplicación se actualizará a SdkState.ON_CALL y se actualizará la interfaz de usuario:

Finalizar la llamada
Para finalizar la llamada necesitamos lanzar el método en la aplicación nativa de Android usando platformMethodChannel. Dentro de main.dart cuerpo de actualización del _endCall del método:
Future<void> _endCall() async {
try {
await platformMethodChannel.invokeMethod('endCall');
} on PlatformException catch (e) {}
}El método anterior se comunicará con Android por lo que tenemos que actualizar el código en la clase MainActivity clase. Añadir endCall a la sentencia when dentro del método 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()
}
}Ahora en el mismo archivo añade el 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)
}
})
}El método anterior establece el estado de la aplicación Flutter en SdkState.WAIT y espera la respuesta del Client SDK, que puede ser de error o de éxito. Ambos estados de UI ya están soportados en la aplicación Flutter.
Se ha gestionado la finalización de la llamada pulsando el botón END CALL en la interfaz de usuario de la aplicación Flutter; sin embargo, la llamada también puede finalizar fuera de la aplicación Flutter, por ejemplo, la llamada será rechazada o contestada y posteriormente finalizada por el receptor de la llamada (en el teléfono real).
Para soportar estos casos tenemos que añadir NexmoCallEventListener a la instancia de llamada y escuchar los eventos específicos de la llamada.
Defina la propiedad callEventListener en la parte superior de la clase MainActivity clase:
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) {}
}La dirección onMemberStatusUpdated callback nos informa de que la llamada ha finalizado.
Para registrar el listener anterior modifique onSuccess callback dentro de makeCall del método:
onGoingCall = call
onGoingCall?.addCallEventListener(callEventListener)Por último, modifique el método endCall para anular el registro del callEventListener listener dentro de onSuccess callback:
onGoingCall?.removeCallEventListener(callEventListener)
onGoingCall = nullEjecute la aplicación y, si ha seguido este tutorial paso a paso, podrá realizar una llamada telefónica desde nuestra aplicación móvil a un número de teléfono físico.
Resumen
Has creado la aplicación con éxito. Al hacerlo, hemos aprendido a realizar una llamada telefónica desde una aplicación móvil al teléfono usando Vonage Client SDK. Para ver la versión completa, consulta este proyecto en GitHub.
Para familiarizarse con otros casos de uso, consulte otros tutoriales y Centro para desarrolladores de Vonage.