
App-To-Phone-Anrufe mit iOS und Flutter
Lesedauer: 11 Minuten
Heute werden wir eine iOS
Anwendung mit Flutter und nutzen das Vonage Client SDK um einen Anruf von einer mobilen Anwendung auf das Telefon zu tätigen. Vonage Gesprächs-API. Die Anwendung wird 3 Bildschirme (3 UI-Zustände) haben:
UI states: logon, make a call, and end call
Voraussetzungen
Der Quellcode für unsere Flutter iOS
Anwendung ist verfügbar auf GitHub.
Bevor wir mit der Erstellung der Flutter
Anwendung für das iOS
Gerät zu erstellen, müssen wir die folgenden Voraussetzungen erfüllen:
Erstellen Sie ein Call Control Object (NCCO)
Installieren Sie die
Vonage CLI
(zuvorNexmo CLI
)Einrichten der
Vonage application
Installieren Sie die
Flutter SDK
Erstellen Sie das
Flutter
Projekt
Vonage-Anwendung
Ein NCCO erstellen
A Anrufsteuerungsobjekt (NCCO) ist ein JSON
Array, das wir zur Steuerung des Ablaufs einer Voice API call
.
Die NCCO
muss öffentlich und über das Internet zugänglich sein. Um dies zu erreichen, werden wir in diesem Tutorial Folgendes verwenden GitHub Gist das eine bequeme Möglichkeit bietet, die Konfiguration zu hosten. Fügen wir einen neuen Gist hinzu:
Besuchen Sie https://gist.github.com/ (wir müssen bei Github angemeldet sein)
Erstellen Sie einen neuen Gist mit
ncco.json
als DateinameKopieren und fügen Sie das folgende
JSON
Objekt in den Gist ein:
[
{
"action": "talk",
"text": "Please wait while we connect you."
},
{
"action": "connect",
"endpoint": [
{
"type": "phone",
"number": "PHONE_NUMBER"
}
]
}
]
Ersetzen Sie
PHONE_NUMBER
durch Ihre Rufnummer (Vonage-Nummern sind im E.164-Format,+
und-
sind nicht gültig. Stellen Sie sicher, dass Sie bei der Eingabe der Nummer die Landesvorwahl angeben, z. B. US: 14155550100 und UK: 447700900001)Klicken Sie auf die
Create secret gist
SchaltflächeKlicken Sie auf die
Raw
SchaltflächeNotieren Sie sich die im Browser angezeigte URL, wir werden sie im nächsten Schritt verwenden
Vonage CLI installieren
Die Vonage CLI ermöglicht es uns, viele Vorgänge über die Befehlszeile auszuführen. Wenn wir Aufgaben wie das Erstellen von Anwendungen, das Anlegen von Gesprächen, den Kauf von Vonage-Nummern usw. ausführen möchten, müssen wir die Vonage CLI installieren.
Vonage CLI erfordert Node.js
also müssen wir zuerst Node.js installieren.
Um die Beta-Version des CLIs mit npm zu installieren, führen Sie diesen Befehl aus:
npm install nexmo-cli@beta -g
Richten Sie die Vonage CLI
zur Verwendung der Vonage API Key
und API Secret
. Diese können wir auf der Einstellungsseite im Dashboard.
Führen Sie den folgenden Befehl im Terminal aus und ersetzen Sie dabei API_KEY
und API_SECRET
durch Werte aus der Datei Dashboard:
nexmo setup API_KEY API_SECRET
Vonage-Anwendung einrichten
Erstellen Sie das Projektverzeichnis. Führen Sie den folgenden Befehl im Terminal aus:
mkdir vonage-tutorial
Wechseln Sie in das Projektverzeichnis:
cd vonage-tutorial
Erstellen Sie eine Vonage-Anwendung, indem Sie den unten stehenden Befehl kopieren und in das Terminal einfügen. Vergewissern Sie sich, dass Sie den Wert von
--voice-answer-url
Argument durch Ersetzen vonGIST-URL
durch die Gist-URL aus dem vorherigen Schritt ersetzen.
nexmo app:create "App to Phone Tutorial" --capabilities=voice --keyfile=private.key --voice-event-url=https://example.com/ --voice-answer-url=GIST-URL
Notieren Sie sich die Application ID
die bei der Erstellung der Anwendung im Terminal ausgegeben wird.
HINWEIS: Eine versteckte Datei namens
.nexmo-app
wird im Projektverzeichnis erstellt und enthält den neu erstelltenVonage Application ID
und den privaten Schlüssel. Eine private Schlüsseldatei mit dem Namenprivate.key
wird ebenfalls im aktuellen Ordner erstellt.
Benutzer erstellen
Jeder Teilnehmer wird durch einen Benutzer Objekt repräsentiert und muss durch das Client SDK
. In einer Produktionsanwendung würden wir diese Benutzerinformationen normalerweise in einer Datenbank speichern.
Führen Sie den folgenden Befehl aus, um einen Benutzer namens Alice
:
nexmo user:create name="Alice"
JWT generieren
Die JWT
wird zur Authentifizierung des Benutzers verwendet. Führen Sie den folgenden Befehl im Terminal aus, um eine JWT
für den Benutzer Alice
. Ersetzen Sie im folgenden Befehl die APPLICATION_ID
durch die ID der Anwendung:
nexmo jwt:generate sub=Alice exp=$(($(date +%s)+86400)) acl='{"paths":{"/*/users/**":{},"/*/conversations/**":{},"/*/sessions/**":{},"/*/devices/**":{},"/*/image/**":{},"/*/media/**":{},"/*/push/**":{},"/*/knocking/**":{},"/*/legs/**":{}}}' application_id=APPLICATION_ID
Mit dem obigen Befehl wird der Ablauf der JWT
auf einen Tag ab jetzt, was das Maximum ist.
Notieren Sie sich die JWT
die wir für Alice
.
HINWEIS: In einer Produktionsumgebung sollte die Anwendung einen Endpunkt bereitstellen, der für jede Client-Anfrage eine
JWT
für jede Client-Anfrage erzeugt.
Xcode installieren
AppStore öffnen und installieren Xcode.
Flatter-Einrichtung
Flutter SDK installieren
Herunterladen und installieren Flutter SDK
.
Dieser Schritt variiert je nach MacOS
, Win
, und Linux
variieren, aber im Allgemeinen läuft es auf das Herunterladen von Flutter SDK
für ein bestimmtes Betriebssystem herunter, extrahiert die Flutter SDK
Datei zu extrahieren und den sdk\bin
Ordner zur System PATH
Variable hinzuzufügen. Eine detaillierte Anleitung für alle Plattformen finden Sie hier.
Zum Glück, Flutter
ein Werkzeug zur Verfügung, mit dem wir überprüfen können, ob SDK
und alle erforderlichen "Komponenten" vorhanden und korrekt konfiguriert sind. Führen Sie diesen Befehl aus:
flutter doctor
Flutter Doctor
prüft, ob Flutter SDK
installiert ist und andere Komponenten korrekt installiert und konfiguriert sind.
Flutter-Projekt erstellen
Wir erstellen ein Flutter
Projekt mit Hilfe des Terminals:
flutter create app_to_phone_flutter
Der obige Befehl erstellt app_to_phone_flutter
Ordner, der das Flutter
Projekt.
Flutter
Projekt enthältios
Ordner, der dasiOS
Projekt;android
Ordner, der dasAndroid
Projekt enthält; undweb
Ordner, der dasweb
Projekt.
Öffnen Sie die pubspec.yaml
Datei, und fügen Sie permission_handler
Abhängigkeit (direkt unter sdk: flutter
):
dependencies:
flutter:
sdk: flutter
permission_handler: ^6.0.1+1
Die Einrückung ist wichtig in
yaml
Dateien wichtig, stellen Sie also sicher, dasspermission_handler
auf der gleichen Einrückungsebene liegt wie derflutter:
Element.
Führen Sie nun diesen Befehl aus (der Pfad ist das Stammverzeichnis des Flutter
Projekts), um die oben genannte Abhängigkeit herunterzuladen:
flutter pub get
Der obige Befehl erstellt auch Podfile
in ios
Unterordner. Öffnen Sie ios\Podfile
unkommentiert platform
Zeile und aktualisieren Sie die Plattformversion auf 11
:
platform :ios, '11.0'
Am Ende der gleichen Datei hinzufügen pod 'NexmoClient'
:
target 'Runner' do
use_frameworks!
use_modular_headers!
pod 'NexmoClient'
Öffnen Sie app_to_phone_flutter/ios
Ordner im Terminal und installieren Sie Pods:
pod install
Mit dem obigen Befehl werden alle erforderlichen Abhängigkeiten heruntergeladen, einschließlich Flutter
, Berechtigungshandler, und Client SDK
.
Öffnen Sie Runner.xcworkspace
in Xcode
und führen Sie die Anwendung aus, um zu überprüfen, ob die obige Einrichtung korrekt durchgeführt wurde.
Zwei-Wege-Flutter/iOS-Kommunikation
Derzeit, Client SDK
ist nicht als Flutter
Paket verfügbar, daher müssen wir das Android natives Client SDK verwenden und die Kommunikation zwischen iOS
und Flutter
über Methoden-Kanal - auf diese Weise, Flutter
werden Android-Methoden aufgerufen, iOS
ruft Flutter
Methoden.
Der Flutter-Code wird in der Datei lib/main.dart
Datei gespeichert, während iOS
nativer Code wird in der Datei ios/Runner/AppDelegate.swift
Datei gespeichert wird.
Init Flutter Anwendung
Flutter-Anwendungen werden mit einer Programmiersprache namens Dart.
Öffnen Sie die Datei lib/main.dart
Datei und ersetzen Sie den gesamten Inhalt durch den folgenden Code:
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
}
Der obige Code enthält eine benutzerdefinierte CallWidget
die für die Verwaltung des Anwendungsstatus (Protokollierung des Benutzers und Verwaltung des Anrufs) zuständig ist. Die SdkState
enum repräsentiert mögliche Zustände von Vonage Client SDK
. Dieses Enum wird zweimal definiert - einmal für Flutter mit Dart
und eine für iOS
Verwendung von Swift. Das Widget enthält die _updateView
Methode, die das UI basierend auf dem SdkState
Wert.
Führen Sie die Anwendung vom Xcode
:
Running the application from xcode
Die Schaltfläche Login as Alice
Schaltfläche sollte angezeigt werden:
Logged out screen showing Login as Alice button
Anmeldebildschirm
Die Schaltfläche Login as Alice
Schaltfläche ist deaktiviert, also fügen Sie jetzt onPressed
Handler zu der ElevatedButton
um die Anmeldung zu ermöglichen:
Widget _updateView() {
if (_sdkState == SdkState.LOGGED_OUT) {
return ElevatedButton(
onPressed: () { _loginUser(); },
child: Text("LOGIN AS ALICE")
);
}
}
Aktualisieren Sie den Körper der _loginUser
Methode, um mit dem nativen Code zu kommunizieren und den Benutzer anzumelden:
Future<void> _loginUser() async {
String token = "ALICE_TOKEN";
try {
await platformMethodChannel.invokeMethod('loginUser', <String, dynamic>{'token': token});
} on PlatformException catch (e) {
print(e);
}
}
Ersetzen Sie die ALICE_TOKEN
durch das JWT
Token, das wir zuvor von Vonage CLI
zur Authentifizierung des Benutzers Alice
für den Zugriff auf die Konversation zu authentifizieren. Flutter
ruft die loginUser
Methode auf und übergibt die token
als Argument übergeben. Die Methode loginUser
Methode ist definiert in der MainActivity
Klasse definiert (dazu kommen wir gleich noch). Um diese Methode von Flutter
aufzurufen, müssen wir eine MethodChannel
. hinzufügen. platformMethodChannel
Feld am Anfang der _CallWidgetState
Klasse:
hinzufügen platformMethodChannel
Feld am Anfang von _CallWidgetState
Klasse:
class _CallWidgetState extends State<CallWidget> {
SdkState _sdkState = SdkState.LOGGED_OUT;
static const platformMethodChannel = const MethodChannel('com.vonage');
Die com.vonage
steht für die eindeutige Kanal-ID, die wir auch dem nativen iOS
Code (AppDelegate
Klasse). Nun müssen wir diesen Methodenaufruf auf der nativen iOS
Seite behandeln.
Öffnen Sie ios/Runner/AppDelegate
Klasse und vonageChannel
Eigenschaft, die den Verweis auf die FlutterMethodChannel
:
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var vonageChannel: FlutterMethodChannel?
...
Um auf Methodenaufrufe zu warten, die von Flutter
hinzufügen addFlutterChannelListener
Methode innerhalb der AppDelegate
Klasse (gleiche Ebene wie obige application
Methode):
func addFlutterChannelListener() {
let controller = window?.rootViewController as! FlutterViewController
vonageChannel = FlutterMethodChannel(name: "com.vonage",
binaryMessenger: controller.binaryMessenger)
vonageChannel?.setMethodCallHandler({ [weak self]
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
guard let self = self else { return }
switch(call.method) {
case "loginUser":
if let arguments = call.arguments as? [String: String],
let token = arguments["token"] {
self.loginUser(token: token)
}
result("")
default:
result(FlutterMethodNotImplemented)
}
})
}
Die obige Methode "übersetzt" die Flutter
Methodenaufrufe in Methoden, die in der AppDelegate
Klasse (die loginUser
für jetzt).
Und es fehlen die loginUser
Methoden innerhalb derselben Klasse (wir werden den Körper bald füllen):
func loginUser(token: String) {
}
Jetzt hinzufügen addFlutterChannelListener
Methodenaufruf innerhalb der application
Methode ein:
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
addFlutterChannelListener()
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
Der Code ist vorhanden - nach dem Drücken des Login As Alice
Schaltfläche ruft die Flutter-App die _loginUser
Methode auf. Über den Flutter
Plattformkanal ruft die Methode die loginUser
Methode auf, die in der AppDelegate
Klasse definiert ist.
Führen Sie die Anwendung von Xcode
um sicherzustellen, dass sie kompiliert wird.
Bevor wir uns als Benutzer anmelden können, müssen wir die Initialisierung der Vonage SDK Client
.
Client initialisieren
Öffnen Sie AppDelegate
Klasse und fügen Sie den NexmoClient
Import am Anfang der Datei hinzu:
import NexmoClient
In der gleichen Datei fügen Sie client
Eigenschaft, die einen Verweis auf Vonage Client
.
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var vonageChannel: FlutterMethodChannel?
let client = NXMClient.shared
...
Jetzt hinzufügen initClient
Methode hinzu, um den Client zu initialisieren:
func initClient() {
client.setDelegate(self)
}
Zum Aufruf der initClient
Methode von der bestehenden application
Methode aufzurufen, müssen wir die initClient()
Zeile hinzufügen, wie im folgenden Beispiel gezeigt:
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
initClient()
addFlutterChannelListener()
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
Bevor wir eine Konversation zulassen, müssen wir wissen, dass der Benutzer korrekt angemeldet ist. In der AppDelegate
Datei einen Delegaten hinzufügen, der auf Vonage Client SDK
Änderungen des Verbindungsstatus:
extension AppDelegate: NXMClientDelegate {
func client(_ client: NXMClient, didChange status: NXMConnectionStatus, reason: NXMConnectionStatusReason) {
switch status {
case .connected:
notifyFlutter(state: .loggedIn)
case .disconnected:
notifyFlutter(state: .loggedOut)
case .connecting:
notifyFlutter(state: .wait)
@unknown default:
notifyFlutter(state: .error)
}
}
}
Schließlich muss die notifyFlutter
Methode zur gleichen Klasse hinzugefügt werden:
func client(_ client: NXMClient, didReceiveError error: Error) {
notifyFlutter(state: .error)
}
}
Anmeldung des Benutzers
Ändern Sie loginUser
Methodenkörper zum Aufruf login
auf der Client-Instanz aufzurufen:
func loginUser(token: String) {
self.client.login(withAuthToken: token)
}
Diese Methode ermöglicht es uns, den Benutzer (Alice
) unter Verwendung der Client SDK
auf die Konversation zuzugreifen.
Flutter über Client SDK Statusänderung benachrichtigen
Zur Mitteilung Flutter
über alle Änderungen des Zustands in der Client SDK
zu benachrichtigen, müssen wir ein enum
hinzufügen, das die Zustände der Client SDK
. Wir haben bereits das entsprechende SdkState
Aufzählung in der main.dart
Datei hinzugefügt. Fügen Sie die folgende SdkState
enum, am Ende der Datei MainActivity.kt
Datei:
enum SdkState: String {
case loggedOut = "LOGGED_OUT"
case loggedIn = "LOGGED_IN"
case wait = "WAIT"
case onCall = "ON_CALL"
case error = "ERROR"
}
Um diese Zustände an Flutter
(vom obigen Delegaten) zu senden, müssen wir die notifyFlutter
Methode in der AppDelegate
Klasse hinzufügen:
func notifyFlutter(state: SdkState) {
vonageChannel?.invokeMethod("updateState", arguments: state.rawValue)
}
Beachten Sie, dass wir den Status in der Aufzählung speichern, ihn aber als String senden.
SDK-Status-Update durch Flutter abrufen
Zum Abrufen von Statusaktualisierungen in Flutter
abzurufen, müssen wir auf Aktualisierungen des Methodenkanals warten. Öffnen Sie main.dart
Datei und fügen Sie _CallWidgetState
Konstruktor mit benutzerdefiniertem Handler:
_CallWidgetState() {
platformMethodChannel.setMethodCallHandler(methodCallHandler);
}
Innerhalb der gleichen Klasse (_CallWidgetState
) fügen Sie die Handler-Methode hinzu:
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');
}
}
Diese Methoden empfangen das "Signal" von Android und wandeln es in ein Enum um. Aktualisieren Sie nun den Inhalt der _updateView
Methode zur Unterstützung von SdkState.WAIT
und SdkState.LOGGED_IN
Zustände, wie im folgenden Beispiel gezeigt:
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")
);
}
}
Während SdkState.WAIT
wird der Fortschrittsbalken angezeigt. Nach erfolgreicher Anmeldung zeigt die Anwendung die MAKE PHONE CALL
Schaltfläche.
Starten Sie die Anwendung und klicken Sie auf die Schaltfläche mit der Aufschrift LOGIN AS ALICE
. Die Schaltfläche MAKE PHONE CALL
Schaltfläche sollte erscheinen, die einen anderen Zustand der Flutter
App basierend auf der SdkState
enum`). Ein Beispiel hierfür ist im folgenden Bild zu sehen:
Make a phone call UI state
Anrufen
Jetzt müssen wir eine Funktion zum Telefonieren hinzufügen. Öffnen Sie die main.dart
Datei und aktualisieren Sie den Körper der _makeCall
Methode wie unten gezeigt:
Future<void> _makeCall() async {
try {
await platformMethodChannel
.invokeMethod('makeCall');
} on PlatformException catch (e) {
print(e);
}
}
Die obige Methode kommuniziert mit iOS
kommunizieren, also müssen wir den Code in der AppDelegate
Klasse ebenfalls aktualisieren. Fügen Sie makeCall
Klauseln zu der switch
Anweisung innerhalb der addFlutterChannelListener
Methode:
func addFlutterChannelListener() {
let controller = window?.rootViewController as! FlutterViewController
vonageChannel = FlutterMethodChannel(name: "com.vonage",
binaryMessenger: controller.binaryMessenger)
vonageChannel?.setMethodCallHandler({ [weak self]
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
guard let self = self else { return }
switch(call.method) {
case "loginUser":
if let arguments = call.arguments as? [String: String],
let token = arguments["token"] {
self.loginUser(token: token)
}
result("")
case "makeCall":
self.makeCall()
result("")
default:
result(FlutterMethodNotImplemented)
}
})
}
Fügen Sie nun in der gleichen Datei die Eigenschaft onGoingCall
hinzu, die definiert, ob und wann ein Anruf läuft:
var onGoingCall: NXMCall?
HINWEIS: Derzeit speichert die
Client SDK
keine laufende Aufrufreferenz, daher müssen wir sie in derAppDelegate
Klasse speichern. Wir werden sie später zum Beenden des Anrufs verwenden.
Fügen Sie nun in der gleichen Klasse makeCall
Methode:
func makeCall() {
client.call("IGNORED_NUMBER", callHandler: .server) { [weak self] (error, call) in
guard let self = self else { return }
if error != nil {
self.notifyFlutter(state: .error)
return
}
self.onGoingCall = call
self.notifyFlutter(state: .onCall)
}
}
Die obige Methode setzt den Status der Flutter
App auf SdkState.WAIT
und wartet auf die Client SDK
Antwort (Fehler oder Erfolg). Jetzt müssen wir die Unterstützung für beide Zustände hinzufügen (SdkState.ON_CALL
und SdkState.ERROR
) innerhalb der main.dart
Datei hinzufügen. Aktualisieren Sie den Körper der _updateView
Methode, um das Gleiche wie unten zu zeigen:
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")
);
}
}
Jede Zustandsänderung führt zu einer Änderung der Benutzeroberfläche. Bevor ein Anruf getätigt wird, benötigt die Anwendung bestimmte Berechtigungen für die Nutzung des Mikrofons. Im nächsten Schritt werden wir die Funktionalität in das Projekt aufnehmen, um diese Berechtigungen anzufordern.
Berechtigungen anfordern
Die Anwendung muss auf das Mikrofon zugreifen können, also müssen wir den Zugriff auf das Mikrofon anfordern (Permission.microphone
für Flutter
).
Öffnen Sie ios/Runner/info.plist
Datei und fügen Sie Privacy - Microphone Usage Description
Schlüssel mit Make a call
Wert:
Setting add microphone permission
Wir haben bereits den permission_handler Paket zum Flutter
Projekt hinzugefügt. Jetzt müssen wir am Anfang der main.dart
Datei müssen wir das permission_handler
Paket importieren, wie im folgenden Beispiel gezeigt:
import 'package:permission_handler/permission_handler.dart';
Um die Anfrage für bestimmte Berechtigungen auszulösen, müssen wir die requestPermissions()
Methode innerhalb der _CallWidgetState
Klasse innerhalb der main.dart
Datei hinzufügen. Fügen Sie also diese neue Methode innerhalb der Klasse hinzu:
Future<void> requestPermissions() async {
await [ Permission.microphone ].request();
}
Die obige Methode wird die Berechtigungen mit permission_handler
.
Ändern Sie in derselben Klasse den Körper der Klasse _makeCall
Klasse so, dass vor dem Aufruf der Methode über den Methodenkanal Berechtigungen angefordert werden:
Future<void> _makeCall() async {
try {
await requestPermissions();
...
}
Starten Sie die App und klicken Sie auf MAKE PHONE CALL
um einen Anruf zu starten. Der Berechtigungsdialog wird angezeigt, und nachdem Sie die Berechtigungen erteilt haben, wird der Anruf gestartet.
Zur Erinnerung: Wir haben die Rufnummer bereits in der
NCCO
Der Status der Anwendung wird aktualisiert auf SdkState.ON_CALL
und die Benutzeroberfläche wird aktualisiert:
On call UI
Anruf beenden
Um den Aufruf zu beenden, müssen wir die Methode in der nativen iOS
Anwendung mit platformMethodChannel
. Innerhalb der main.dart
Datei aktualisieren wir den Körper der _endCall
Methode:
Future<void> _endCall() async {
try {
await platformMethodChannel.invokeMethod('endCall');
} on PlatformException catch (e) {}
}
Die obige Methode kommuniziert mit iOS
kommunizieren, also müssen wir den Code in der AppDelegate
Klasse ebenfalls aktualisieren. Fügen Sie endCall
Klauseln zu der switch
Anweisung innerhalb der addFlutterChannelListener
Methode:
func addFlutterChannelListener() {
let controller = window?.rootViewController as! FlutterViewController
vonageChannel = FlutterMethodChannel(name: "com.vonage",
binaryMessenger: controller.binaryMessenger)
vonageChannel?.setMethodCallHandler({ [weak self]
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
guard let self = self else { return }
switch(call.method) {
case "loginUser":
if let arguments = call.arguments as? [String: String],
let token = arguments["token"] {
self.loginUser(token: token)
}
result("")
case "makeCall":
self.makeCall()
result("")
case "endCall":
self.endCall()
result("")
default:
result(FlutterMethodNotImplemented)
}
})
}
Fügen Sie nun in der gleichen Klasse die endCall
Methode hinzu:
func endCall() {
onGoingCall?.hangup()
onGoingCall = nil
notifyFlutter(state: .loggedIn)
}
Die obige Methode setzt den Status der Flutter
App auf SdkState.WAIT
und wartet auf die Antwort von Client SDK
die entweder ein Fehler oder ein Erfolg sein kann. Beide UI-Zustände werden bereits in der Flutter
Anwendung (_updateView
Methode).
Wir haben das Beenden des Anrufs durch Drücken der END CALL
Schaltfläche in der Flutter
Anwendungs-UI. Der Anruf kann jedoch auch außerhalb der Anwendung beendet werden. Flutter
App beendet werden, z. B. indem der Anruf abgewiesen oder angenommen und später vom Anrufer (auf dem echten Telefon) beendet wird.
Um diese Fälle zu unterstützen, müssen wir den NexmoCallEventListener
Listener zur Anrufinstanz hinzufügen und auf anrufspezifische Ereignisse warten.
In der Datei AppDelegares.swift
Datei hinzufügen NXMCallDelegate
:
extension AppDelegate: NXMCallDelegate {
func call(_ call: NXMCall, didUpdate callMember: NXMCallMember, with status: NXMCallMemberStatus) {
if (status == .completed || status == .cancelled) {
onGoingCall = nil
notifyFlutter(state: .loggedIn)
}
}
func call(_ call: NXMCall, didUpdate callMember: NXMCallMember, isMuted muted: Bool) {
}
func call(_ call: NXMCall, didReceive error: Error) {
notifyFlutter(state: .error)
}
}
Um den obigen Hörer zu registrieren, ändern Sie onSuccess
Callback innerhalb der makeCall
Methode:
func makeCall() {
client.call("IGNORED_NUMBER", callHandler: .server) { [weak self] (error, call) in
guard let self = self else { return }
if error != nil {
self.notifyFlutter(state: .error)
return
}
self.onGoingCall = call
self.onGoingCall?.setDelegate(self)
self.notifyFlutter(state: .onCall)
}
}
Führen Sie die App aus und rufen Sie von der mobilen Anwendung aus eine physische Telefonnummer an.
Zusammenfassung
Wir haben die Anwendung erfolgreich erstellt. Dabei haben wir gelernt, wie man einen Anruf von einer mobilen Anwendung auf das Telefon mit Vonage tätigt Client SDK
. Das komplette Projekt finden Sie auf GitHub. Dieses Projekt enthält zusätzlich den nativen Android-Code (android
Ordner), der es uns ermöglicht, die App auch auf Android laufen zu lassen.
Um sich mit anderen Funktionalitäten vertraut zu machen, lesen Sie bitte andere Tutorials und Vonage Entwicklerzentrum.