
Aufbau eines App-To-Phone-Anrufs mit Android und Flutter
Lesedauer: 11 Minuten
Heute werden wir eine Android-Anwendung mit Flutter erstellen und das Vonage Client SDK verwenden, um einen Anruf von einer mobilen Anwendung zum Telefon zu tätigen. Die Anwendung wird 3 Bildschirme (3 UI-Status) haben:

Voraussetzungen
Der Quellcode ist verfügbar auf GitHub.
Bevor wir mit der Erstellung der Anwendung für unser Android-Gerät beginnen, müssen Sie die folgenden Voraussetzungen erfüllen:
Erstellen Sie ein Call Control Object (NCCO)
Installieren Sie die Vonage CLI
Einrichten einer Vonage-Anwendung
Installieren Sie das Flutter SDK
Ein Flutter-Projekt erstellen
Vonage-Anwendung
Ein NCCO erstellen
Ein Call Control Object (NCCO) ist ein JSON-Array, das wir zur Steuerung des Ablaufs eines Voice API-Aufrufs verwenden. Weitere Informationen zu NCCO finden Sie hier hier.
Das NCCO muss öffentlich und über das Internet zugänglich sein. Um dies zu erreichen, werden Sie in diesem Tutorium 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/ (Sie müssen bei Github eingeloggt sein)
Erstellen Sie einen neuen Gist mit
ncco.jsondem als DateinamenKopieren Sie das folgende JSON-Objekt und fügen Sie es in die Gist ein:
[
{
"action": "talk",
"text": "Please wait while we connect you."
},
{
"action": "connect",
"endpoint": [
{
"type": "phone",
"number": "PHONE_NUMBER"
}
]
}
]Ersetzen Sie
PHONE_NUMBERdurch unsere Telefonnummer (Vonage Numbers sind im E.164-Format https://developer.nexmo.com/concepts/guides/glossary#e-164-format'+' und '-' sind nicht gültig. Vergewissern Sie sich, dass wir bei der Eingabe unserer Numbers unsere Landesvorwahl angeben, z. B. US: 14155550100 und UK: 447700900001)Klicken Sie auf die
Create secret gistSchaltflächeKlicken Sie auf die
RawSchaltflächeNotieren Sie sich die in unserem 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 die Erstellung von Applications, den Kauf von Vonage Numbers usw. durchführen wollen, müssen wir die Vonage CLI installieren.
Vonage CLI erfordert node.jsalso müssen wir zuerst node.js installieren, indem wir diese Anweisungen.
Um die Beta-Version der CLI mit NPM zu installieren, führen Sie diesen Befehl aus:
npm install @vonage/cli -gRichten Sie die Vonage CLI so ein, dass sie unseren Vonage API-Schlüssel und unser API-Geheimnis verwendet. Seite Einstellungen im Dashboard.
Führen Sie den folgenden Befehl in einem Terminal aus und ersetzen Sie dabei api_key und api_secret durch unsere eigenen:
vonage config:set --apiKey=api_key --apiSecret=api_secret Vonage-Anwendung einrichten
Erstellen Sie unser Projektverzeichnis, falls Sie dies noch nicht getan haben, und führen Sie den folgenden Befehl im Terminal aus:
mkdir vonage-tutorial2. Wechseln Sie in das Projektverzeichnis:
cd vonage-tutorial3. Erstellen Sie eine Vonage-Anwendung, indem Sie den folgenden Befehl kopieren und in das Terminal einfügen Ändern Sie den Wert von --voice-answer-url Argument durch Ersetzen von GIST-URL durch die Gist-URL aus dem vorherigen Schritt ersetzen.
vonage apps:create "App to Phone Tutorial" --voice_event_url=https://example.com/ --voice_answer_url=GIST-URLNotieren Sie sich die Anwendungs-ID, die bei der Erstellung unserer Anwendung in unserem Terminal ausgegeben wird.
HINWEIS: Eine Datei namens
vonage_app.jsonwird in unserem Projektverzeichnis erstellt und enthält die neu erstellte Vonage-Anwendungs-ID und den privaten Schlüssel. Eine private Schlüsseldatei namensapp_to_phone_tutorial.keywird ebenfalls erstellt.
Benutzer erstellen
Jeder Teilnehmer wird durch einen Benutzer Objekt repräsentiert und muss durch das Client SDK authentifiziert werden. 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
vonage apps:users:create Alice JWT generieren
Das JWT wird zur Authentifizierung des Benutzers verwendet. Führen Sie den folgenden Befehl im Terminal aus, um ein JWT für den Benutzer zu erzeugen Alice.
Ersetzen Sie in dem folgenden Befehl die APPLICATION_ID durch die ID unserer Anwendung:
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/**": {}
}
}'Mit dem obigen Befehl wird der Ablauf des JWT auf einen Tag ab jetzt festgelegt, was das Maximum darstellt.
Notieren Sie sich das JWT, das wir für Alice.
HINWEIS: In einer Produktionsumgebung sollte unsere Anwendung einen Endpunkt bereitstellen, der für jede Client-Anfrage ein JWT erzeugt.
Android Studio installieren
Herunterladen und installieren Android-Studio.
Flatter-Einrichtung
Flutter SDK installieren
Dieser Schritt variiert unter MacOS, Win und Linux, aber im Allgemeinen läuft es darauf hinaus, das Flutter-SDK für ein bestimmtes Betriebssystem herunterzuladen, die SDK-Datei zu extrahieren und den sdk\bin Ordner zur System-PATH-Variable hinzuzufügen. Eine detaillierte Anleitung finden Sie hier.
Glücklicherweise verfügt Flutter über ein Tool, mit dem wir überprüfen können, ob das SDK und alle erforderlichen "Komponenten" vorhanden und korrekt konfiguriert sind. Führen Sie diesen Befehl aus:
flutter doctorFlutter Doctor verifiziert, ob das Flutter SDK installiert ist und andere Komponenten korrekt installiert und konfiguriert sind. Wenn Probleme erkannt werden, werden wir die Beschreibung und den Hinweis zur Behebung sehen.
Installieren Sie das Flutter-Plugin
Öffnen Sie Android-Studio, gehen Sie zu Preferences | plugins und installieren Sie Flutter- und Dart-Plugins vom Marktplatz.
Das Flutter-Plugin fügt eine neue Symbolleiste hinzu, die das Ausführen und Debuggen von Flutter-Anwendungen ermöglicht:

Erstellen Sie das Flutter-Projekt
Sie werden ein Flutter-Projekt mit Android Studio erstellen.
Android Studio ausführen
Wählen Sie auf dem Begrüßungsbildschirm von Android Studio
Create New Flutter project

Wählen Sie
Flutter Applicationund klicken SieNextGeben Sie
app_to_phone_flutterals Projektnamen ein, geben SieFlutter SDK pathein und klickenNextWählen Sie
Include Kotlin support for Android codeund klicken SieFinish
Beachten Sie, dass
app_to_phone_flutterOrdner (Flutter-Projekt) enthältiosden Ordner mit dem OS-Projekt undiosden Ordner mit dem iOS-Projekt enthält.
Schließen Sie das Android-Gerät oder den Emulator an und führen Sie die App aus, um zu überprüfen, ob alles wie erwartet funktioniert.
Zwei-Wege-Kommunikation Flutter/Android
Derzeit ist das Client SDK nicht als Flutter-Paket verfügbar, so dass wir Folgendes verwenden müssen Android-eigenes Client SDK verwenden und die Kommunikation zwischen Android und Flutter über Methoden-Kanal - auf diese Weise wird Flutter Android-Methoden aufrufen, Android wird Flutter-Methoden aufrufen.
Der Flutter-Code wird in der Datei lib/ain.dart Datei gespeichert, während der native Android-Code in der android/app/src/main/kotlin/com/example/app_to_phone_flutter/MainActivity.kt Datei gespeichert wird.
Init Flutter Anwendung
Flutter Applications 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 einmal für Android mit Kotlin. Das Widget enthält die _updateView Methode, die das UI basierend auf dem SdkState Wert.
Starten Sie die Anwendung über die grüne Pfeilschaltfläche in der Flutter-Symbolleiste:

Wir sollten die Login Alice Schaltfläche:

Anmeldebildschirm
Die Schaltfläche Login as Aice 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 erhalten haben, um den Benutzer zu authentifizieren Alice von Vonage CLI zu authentifizieren. Flutter wird die loginUser Methode auf und übergibt den token als Argument übergeben. Die loginUser Methode ist definiert in der MainActivity Klasse definiert ist (dazu kommen Sie gleich). Um diese Methode von Flutter aus aufzurufen, müssen wir eine MethodChannel. Fügen Sie das platformMethodChannel Feld am Anfang der _CallWidgetState Klasse:
class _CallWidgetState extends State<CallWidget> {
SdkState _sdkState = SdkState.LOGGED_OUT;
static const platformMethodChannel = const MethodChannel('com.vonage');Die com.vonage String steht für die eindeutige Kanal-ID, die wir auch im nativen Android-Code (MainActivity Klasse). Nun müssen wir diesen Methodenaufruf auf der nativen Android-Seite behandeln.
Öffnen Sie MainActivity Klasse. Beachten Sie, dass das Flutter-Plugin einen Hinweis anzeigt, dieses Android-Projekt in einer separaten Instanz von Android Studio (einem anderen Fenster) zu öffnen. Tun Sie dies, um eine bessere Code-Vervollständigung für das Android-Projekt zu erhalten:

HINWEIS: Dies geschieht, weil das Flutter-Projekt aus dem Android-Projekt und dem iOS-Projekt besteht.
Um auf Methodenaufrufe zu lauschen, die von Flutter overide stammen configureFlutterEngine und fügen Sie addFlutterChannelListener Methodenaufruf innerhalb von configureFlutterEngine Methode:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
addFlutterChannelListener()
}Nun fügen Sie addFlutterChannelListener und loginUser Methoden innerhalb der MainActivity Klasse (gleiche Ebene wie die obige configureFlutterEngine Methode):
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")
}Nach dem Ausführen der Anwendung sollten wir eine login with token... Meldung im Android Logcat sehen. Jetzt ist es an der Zeit, eine fehlende client.
Client SDK-Abhängigkeit hinzufügen
Fügen Sie ein benutzerdefiniertes Maven-URL-Repository zu unserer Gradle-Konfiguration hinzu. Fügen Sie den folgenden Maven-Block innerhalb des allprojects Blocks innerhalb der Projekt-Level build.gradle.kts Datei:
allprojects {
repositories {
google()
jcenter()
maven {
url "https://artifactory.ess-dev.com/artifactory/gradle-dev-local"
}
}
}Fügen Sie nun die Client SDK-Abhängigkeit zum Projekt in der app\build.gradle Datei hinzu:
dependencies {
// ...
implementation 'com.nexmo.android:client-sdk:2.8.1'
}In der gleichen Datei setzen Sie min Android SDK Version auf 23:
minSdkVersion 23Führen Sie Sync project with Gradle Befehl in Android Studio, wie im folgenden Beispiel gezeigt:

Client initialisieren
Öffnen Sie MainActivity Klasse und fügen Sie die client Eigenschaft hinzu, die den Verweis auf den Nexmo-Client enthält:
private lateinit var client: NexmoClientJetzt hinzufügen initClient Methode hinzu, um den Client zu initialisieren:
private fun initClient() {
client = NexmoClient.Builder().build(this)
}Zum Aufruf der initClient Methode von der bestehenden Methode configureFlutterEngine Methode aufzurufen, müssen wir die initClient() Zeile hinzufügen, wie im folgenden Beispiel gezeigt:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
initClient()
addFlutterChannelListener()
} Anmeldung Der Benutzer
Ändern Sie login Methodenkörper zum Aufruf login auf der Client-Instanz aufzurufen:
private fun login(token: String) {
client.login(token)
}Dies ermöglicht uns, den Benutzer (Alice) mit Client SDK anzumelden.
Flutter über Client SDK Statusänderung benachrichtigen
Um Flutter über Änderungen am Zustand des SDKs zu informieren, müssen Sie enum hinzufügen, um die Zustände des Client SDK darzustellen. Sie haben bereits das entsprechende SdkState Enum in der main.dart Datei). Fügen Sie die folgendeSdkState enum, am Ende der Datei MainActivity.kt Datei:
enum class SdkState {
LOGGED_OUT,
LOGGED_IN,
WAIT,
ON_CALL,
ERROR
}Als nächstes müssen wir den Verbindungs-Listener hinzufügen und einige der SDK-Zustände auf SdkState enum. Ändern Sie den Körper der initClient Methode wie im folgenden Beispiel gezeigt:
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)
}
}
}Schließlich muss die notifyFlutter Methode in die MainActivity Klasse hinzugefügt werden:
private fun notifyFlutter(state: SdkState) {
Handler(Looper.getMainLooper()).post {
MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, "com.vonage")
.invokeMethod("updateState", state.toString())
}
}Beachten Sie, dass wir den Zustand im Enum speichern, ihn aber als String senden. Die Kommunikation mit Flutter findet auf dem main Thread, also müssen wir mit Handler verwenden, um den Thread zu wechseln. Die MethodChannel ruft die updateState Methode auf, die in der main.dart Datei definiert ist.
SDK-Status von Flutter abrufen
Um Statusaktualisierungen in Flutter abzurufen, müssen wir auf Aktualisierungen des Methodenkanals hören. Öffnen Sie main.dart Datei und fügen Sie diese beiden Methoden hinzu _CallWidgetState Klasse:
_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');
}
}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.
HINWEIS: Beim Ändern von nativem Android-Code funktioniert Flutter Hot Reload nicht. Wir müssen die Anwendung anhalten und erneut ausführen.
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 dem SdkState enum`). Ein Beispiel hierfür ist im folgenden Bild zu sehen:

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 requestPermissions();
await platformMethodChannel
.invokeMethod('makeCall');
} on PlatformException catch (e) {
print(e);
}
}Die obige Methode wird mit Android kommunizieren, also müssen wir den Code in der MainActivity Klasse ebenfalls aktualisieren. Fügen Sie makeCall Klauseln zu when Anweisung innerhalb der addFlutterChannelListener Methode:
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()
}
}
}
}Fügen Sie nun in der gleichen Datei die Eigenschaft onGoingCall hinzu, die definiert, ob und wann ein Anruf läuft:
private var onGoingCall: NexmoCall? = nullHINWEIS: Derzeit speichert das Client SDK keine Referenz auf laufende Anrufe, daher müssen wir sie in der
MainActivityKlasse speichern. Wir werden sie später verwenden, um den Anruf zu beenden.
Fügen Sie nun in der gleichen Datei makeCall Methode:
@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)
}
})
}Die obige Methode setzt den Status der Flutter-App auf SdkState.WAIT und wartet auf die Antwort des Client SDK (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 (Flutter) hinzufügen. Aktualisieren Sie den Körper der _updateView Methode, um das Gleiche wie unten darzustellen:
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 werden kann, benötigt die Anwendung bestimmte Berechtigungen zur Nutzung des Mikrofons. Im nächsten Schritt werden wir in unserem Projekt die Funktionalität hinzufügen, um diese Berechtigungen anzufordern.
Berechtigungen anfordern
Die Anwendung muss in der Lage sein, auf das Mikrofon zuzugreifen, also müssen wir die Erlaubnis von Android android.permission.RECORD_AUDIO Erlaubnis anfordern (Flutter nennt es Permission.microphone).
Zuerst müssen wir die permission_handler Paket hinzufügen. Öffnen Sie pubspec.yaml Datei und fügen Sie permission_handler: ^6.0.1+1 Abhängigkeit unter sdk: flutter:
dependencies:
flutter:
sdk: flutter
permission_handler: ^6.0.1+1Die Einrückung ist wichtig in
yamlDateien wichtig, stellen Sie also sicher, dasspermission_handlerauf der gleichen Einrückungsebene liegt wie derflutter:Element.
Führen Sie den folgenden Befehl im Terminal aus, um das neu hinzugefügte Flutter-Paket herunterzuladen:
flutter pub getAm Anfang der Datei main.dart Datei, müssen Sie 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 Sie 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();
}Schließlich müssen wir noch zwei Berechtigungen (uses-permission Tags) innerhalb der app/src/main/AndroidManifest.xml Datei, oberhalb des application Tag:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
...HINWEIS:
android.permission.INTERNETDie Erlaubnis wird implizit von Android erteilt, so dass wir sie in Flutter nicht explizit anfordern müssen.
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.
Rest: wir haben die Telefonnummer bereits in NCCO definiert
Der Status der Anwendung wird aktualisiert auf SdkState.ON_CALL und die Benutzeroberfläche wird aktualisiert:

Beenden Sie den Anruf
Um den Aufruf zu beenden, müssen wir die Methode in der nativen Android-Anwendung auslösen, indem wir platformMethodChannel. Innerhalb von main.dart der Datei update body der _endCall Methode:
Future<void> _endCall() async {
try {
await platformMethodChannel.invokeMethod('endCall');
} on PlatformException catch (e) {}
}Die obige Methode wird mit Android kommunizieren, also müssen wir den Code in der MainActivity Klasse. Fügen Sie endCall Klauseln zur when Anweisung innerhalb der addFlutterChannelListener Methode:
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()
}
}Fügen Sie nun in der gleichen Datei die endCall Methode:
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)
}
})
}Die obige Methode setzt den Status der Flutter-App auf SdkState.WAIT und wartet auf die Antwort des Client SDK, die entweder ein Fehler oder ein Erfolg sein kann. Beide Zustände der Benutzeroberfläche werden bereits in der Flutter-Anwendung unterstützt.
Sie haben das Beenden des Anrufs durch Drücken der END CALL Button in der Flutter-Anwendung beendet, jedoch kann der Anruf auch außerhalb der Flutter-Anwendung beendet werden, z.B. wird der Anruf abgewiesen oder angenommen und später vom Anrufer (auf dem echten Telefon) beendet.
Um diese Fälle zu unterstützen, müssen wir einen NexmoCallEventListener Listener zur Anrufinstanz hinzufügen und auf anrufspezifische Ereignisse warten.
Definieren Sie die callEventListener Eigenschaft am Anfang der MainActivity Klasse:
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) {}
}Der onMemberStatusUpdated Rückruf informiert uns, dass der Anruf beendet ist.
Um den obigen Hörer zu registrieren, ändern Sie onSuccess Callback innerhalb der makeCall Methode:
onGoingCall = call
onGoingCall?.addCallEventListener(callEventListener)Schließlich ändern Sie endCall Methode, um die Registrierung des callEventListener Hörer innerhalb von onSuccess Rückruf:
onGoingCall?.removeCallEventListener(callEventListener)
onGoingCall = nullFühren Sie die App aus, und wenn Sie diese Anleitung Schritt für Schritt befolgt haben, können Sie von unserer mobilen Anwendung aus einen Anruf an eine physische Telefonnummer tätigen.
Zusammenfassung
Sie haben die Anwendung erfolgreich erstellt. Damit haben wir gelernt, wie man mit dem Vonage Client SDK einen Anruf aus einer mobilen Anwendung auf das Telefon tätigt. Die vollständige Version finden Sie in diesem Projekt auf GitHub.
Um sich mit anderen Anwendungsfällen vertraut zu machen, lesen Sie bitte andere Tutorials und Vonage Entwicklerzentrum.