
Teilen Sie:
Chris ist Developer Advocate bei Nexmo, wo er Entwicklern hilft, ihre globale Kommunikationsplattform zu nutzen. Wenn er nicht gerade auf Konferenzen ist, kann man ihn in der Welt herumreisen sehen.
Telefonanrufe in Android-Apps mit Firebase tätigen und empfangen
Mit Nexmo In-App Voicekönnen Sie mit dem Nexmo Stitch Android SDK und der WebRTC-Technologie ganz einfach Telefonanrufe tätigen und empfangen. In diesem Tutorial zeigen wir Ihnen, wie Sie eine einfache Android-App erstellen, die ausgehende Anrufe tätigen und eingehende Anrufe entgegennehmen kann. Diese Funktionalität könnte dort eingesetzt werden, wo Kunden Anrufe an den Kundendienst tätigen und entgegennehmen möchten, ohne die App zu verlassen.
Um die App zum Laufen zu bringen, verwenden wir Firebase-Funktionen zum Hosten der NCCO und geben ein JWT zurück, mit dem sich die Benutzer anmelden können.
Um diesem Blogbeitrag folgen zu können, sollten Sie einige Kenntnisse in JavaScript haben und in der Lage sein, eine Android-App mit Kotlin zu erstellen.
Bevor wir loslegen
Bevor wir loslegen, benötigen Sie einige Dinge.
Vonage Account
Vonage API-Konto
Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.
Richten Sie die Firebase-Funktion ein.
Als erstes müssen wir ein neues Verzeichnis für unser Firebase-Funktionen-Projekt erstellen und unsere Konfigurationsdateien speichern.
mkdir firebase-functions-nexmo-in-app-calling cd firebase-functions-nexmo-in-app-calling
Nachdem nun ein neues Verzeichnis erstellt wurde, können wir die für Setup-Anweisungen von Firebase folgen und ein neues Projekt erstellen.
npm install -g firebase-tools firebase login firebase init functions
Für dieses Projekt habe ich mich entschieden, JavaScript anstelle von TypeScript zu verwenden.
Wenn Sie, wie ich, nicht in der Lage waren, ein Firebase-Funktionsprojekt über die Kommandozeile zu erstellen, können Sie die Firebase-Konsole besuchen, um ein neues Projekt zu erstellen, und dann firebase use --add von der Kommandozeile aus.
Bearbeiten Sie die Firebase-Funktionen
Die endgültige Version der Methoden, die wir für die Firebase-Funktionen verwenden werden, finden Sie im Repo für diese Demo auf GitHub. Kurz gesagt, wir brauchen drei Endpunkte:
Eine Antwort-URL, die das NCCO hosten wird
Eine Ereignis-URL zur Erfassung von Ereignissen aus der Voice API
Eine URL, die ein JWT zurückgibt, mit dem sich die Benutzer anmelden können
Um die Firebase-Funktionen zu bearbeiten, müssen wir die index.js Datei in dem neuen functions/ Verzeichnis, das Firebase nach der Ausführung von firebase init functions
Werfen wir zunächst einen Blick auf die Antwortmethode
exports.answer = functions.https.onRequest((request, response) => {
//use the `to` query parameter that Nexmo gives us to make a call.
//if `to` is null, then we are receiving a call.
var to = request.query.to
var from = request.query.from
var ncco = [];
if (to) {
ncco.push(
{
action: "talk",
text: "Thank you for calling, you are now being connected."
},
{
"action": "connect",
"from": functions.config().nexmo.from_number,
"endpoint": [
{
"type": "phone",
"number": `${to}`
}
]
}
)
} else {
ncco.push(
{
action: "talk",
text: "You are being connected to the Customer."
},
{
"action": "connect",
"from": from,
"endpoint": [
{
"type": "app",
"user": "Customer"
}
]
})
}
response.json(ncco);
});Da die Voice API von Nexmo eine Antwort-URL pro Applikation verwendet, können wir den NCCO für die Annahme eines eingehenden Anrufs dynamisch anzeigen, wenn der to Abfrageparameter null ist. Wenn der to Abfrageparameter ist nicht null ist, dann zeigen wir den NCCO für einen ausgehenden Anruf an.
Unser Endpunkt für die Bereitstellung eines JWT für Benutzer ist recht einfach. Wir verwenden die Nexmo Node-Bibliothek um ein JWT zu erzeugen. Um die Bibliothek verwenden zu können, müssen wir das Paket installieren.
#Vergewissern Sie sich, dass Sie sich im Verzeichnis /functions befinden, in dem sich die Dateien package.json und index.js befinden npm install nexmo
Nach der Installation der Bibliothek können Sie sicherstellen, dass alles korrekt funktioniert, indem Sie die package.json Datei überprüfen. Sie sollte wie folgt aussehen:
"dependencies": {
"firebase-admin": "~5.12.1",
"firebase-functions": "^1.0.3",
"nexmo": "^2.3.2"
}Sobald die Nexmo Node-Bibliothek installiert ist, können wir sie im jwt-Endpunkt wie folgt verwenden, um eine gültige user_jwt.
exports.jwt = functions.https.onRequest((request, response) => {
response.json({
user_jwt: Nexmo.generateJwt("private.key", {
application_id: functions.config().nexmo.application_id,
sub: "Customer",
exp: new Date().getTime() + 86400,
acl: adminAcl
})
});
});Nachdem wir nun unsere Firebase-Funktionen erstellt haben, werden wir eine Vonage-Anwendung erstellen.
Bereitstellen der Firebase-Funktion
Jetzt, wo die Firebase-Funktionen geschrieben wurden, können wir das Firebase-Projekt bereitstellen. Nach der Bereitstellung der Funktionen erhalten wir von Firebase die URLs für unsere Antwort- und Ereignisendpunkte. Wir können diese URLs verwenden, um unsere Vonage-Anwendung zu erstellen.
#Vergewissern Sie sich, dass Sie sich im Verzeichnis firebase-functions-nexmo-in-app-calling/ befinden, das wir zu Beginn dieses Tutorials erstellt haben firebase deploy --only functions
✔ Funktionen[Antwort]: Erfolgreicher Erstellungsvorgang. URL der Funktion (Antwort): https://your-project-name.cloudfunctions.net/answer ✔ functions[event]: Erfolgreicher Erstellungsvorgang. URL der Funktion (Ereignis): https://your-project-name.cloudfunctions.net/event ✔ functions[jwt]: Erfolgreicher Erstellungsvorgang. Funktions-URL (jwt): https://your-project-name.cloudfunctions.net/jwt
Richten Sie die Vonage-Anwendung ein.
Um eine Anwendung zu erstellen, installieren Sie zunächst die Vonage CLI global mit diesem Befehl:
npm install @vonage/cli -gAls nächstes konfigurieren Sie die CLI mit Ihrem Vonage-API-Schlüssel und -Geheimnis. Sie finden diese Informationen im Entwickler-Dashboard.
vonage config:set --apiKey=VONAGE_API_KEY --apiSecret=VONAGE_API_SECRETJetzt verwenden wir die Antwort und die Ereignis-URL, die uns Firebase im vorherigen Abschnitt zur Verfügung gestellt hat.
# Ensure you're in the firebase-functions-nexmo-in-app-calling/ directory we created at the beginning of this tutorial
vonage apps:create
✔ Application Name … ruling_narwhal
✔ Select App Capabilities › Voice
✔ Create voice webhooks? … yes
✔ Answer Webhook - URL … https://your-project-name.cloudfunctions.net/answer
✔ Answer Webhook - Method › POST
✔ Event Webhook - URL … https://your-project-name.cloudfunctions.net/event
✔ Event Webhook - Method › POST
✔ Allow use of data for AI training? Read data collection disclosure - https://help.nexmo.com/hc/en-us/articles/4401914566036 … no
Creating Application... done
Application Name: ruling_narwhalIhr privater Schlüssel wird in dem von Ihnen erstellten Funktionsverzeichnis gespeichert. Der Schlüssel trägt denselben Namen wie Ihr Projekt.
Notieren Sie die Anwendungs-ID und speichern Sie den privaten Schlüssel im Verzeichnis "functions". Ich empfehle Ihnen, die your_private_key_name.key und .nexmo-app Dateien mit Ihren Anmeldedaten in Ihr .gitignore.
In Anlehnung an Best Practices werden wir einige Umgebungsvariablen Firebase config über die Firebase CLI speichern. Die Firebase-Dokumente enthalten eine Übersicht über die Umgebungskonfiguration.
Jetzt müssen wir die Vonage-Anwendungs-ID in der Firebase-Konfiguration über die Firebase-CLI speichern.
firebase functions:config:set nexmo.application_id="aaaaaaaa-bbbb-cccc-dddd-0123456789ab"
Hinweis: Firebase verlangt, dass die Schlüssel der Konfigurationsvariablen in Kleinbuchstaben geschrieben werden, daher verwenden wir für unsere Variablennamen die Groß- und Kleinschreibung "snake".
Wenn Sie möchten, können Sie die Zeichenfolge des privaten Schlüssels, die in der Datei .nexmo-app Datei aus Ihrer Vonage-Anwendung als Firebase-Konfigurationsvariable hochladen, anstatt die gesamte your_private_key_name.key Datei zu den Firebase-Funktionen hochzuladen.
Verknüpfen Sie eine Rufnummer und einen Benutzer mit unserer Anwendung
Nachdem wir nun unsere Funktionen geschrieben haben, müssen wir eine Nummer kaufen, damit unsere Nutzer von dieser Nummer aus abgehende Anrufe tätigen und in ihrer Android-App eingehende Anrufe empfangen können, wenn jemand diese Nummer wählt. Außerdem müssen wir die Nummer mit unserer Vonage-App verknüpfen.
Sie können eine Nummer von Vonage mieten, indem Sie den folgenden Befehl verwenden (ersetzen Sie die Landesvorwahl durch Ihre Vorwahl). Wenn Sie sich zum Beispiel in den USA befinden, ersetzen Sie GB durch US:
Verknüpfen Sie nun die Nummer mit Ihrer App:
vonage apps:link --number=VONAGE_NUMBER APP_ID Das Android-Projekt einrichten
Wenn Sie sich das fertige Projekt für unsere Android-App ansehen möchten, können Sie den Quellcode auf GitHub einsehen.
Zunächst müssen wir die erforderlichen Bibliotheken hinzufügen. Wir werden das Nexmo Stitch Android SDK, Retrofit und den Moshi Converter von Retrofit verwenden.
dependencies {
implementation 'com.nexmo:stitch:1.8.0'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation "com.squareup.retrofit2:converter-moshi:2.4.0"
}Wir verwenden Nachrüstung um eine GET Anfrage an den JWT-Endpunkt der Firebase-Funktion zu stellen, den uns Firebase CLI zur Verfügung gestellt hat.
//FirebaseFunctionService.kt
interface FirebaseFunctionService {
@GET("jwt")
fun getJWT(): Call<UserJWT>
}
//RetrofitClient.kt
var retrofitClient = Retrofit.Builder()
.baseUrl("https://your-project-name.cloudfunctions.net/")
.addConverterFactory(MoshiConverterFactory.create())
.build()
var retrofitService = retrofitClient.create<FirebaseFunctionService>(FirebaseFunctionService::class.java) Hinzufügen der Anmeldeaktivität
Nachdem wir Retrofit eingerichtet haben, können wir es verwenden, um ein JWT vom JWT-Firebase-Funktionsendpunkt in der LoginActivity. Hier zeige ich den glücklichen Weg wenn wir das Benutzer-JWT abrufen und es für die Anmeldung beim Nexmo Stitch Android SDK verwenden. Das Layout für diese Aktivität ist auf GitHub verfügbar.
class LoginActivity : BaseActivity(), RequestHandler<User>, Callback<UserJWT> {
override fun onCreate(savedInstanceState: Bundle?) {
...
loginBtn.setOnClickListener {
login()
}
}
private fun login() {
showProgress(true)
retrofitService.getJWT().enqueue(this)
}
//Successfully retrieved a JWT from the Firebase Function endpoint
override fun onResponse(call: Call<UserJWT>?, response: Response<UserJWT>?) {
val jwt = response?.body()?.user_jwt
client.login(jwt, this)
}
//User successfully logged in with the Nexmo Stitch SDK
override fun onSuccess(result: User?) {
goToCallActivity()
}
} Hinzufügen der Anrufaktivität
Wir fügen ein einfaches Layout für die Eingabe von Telefonnummern und das Starten und Beenden von Anrufen hinzu. Das Layout für diese Aktivität ist in GitHub verfügbar. Wie zuvor zeige ich den glücklichen Weg des Tätigens und Empfangens eines Anrufs.
class CallActivity : BaseActivity(), RequestHandler<Call> {
private var currentCall: Call? = null
private lateinit var client: ConversationClient
override fun onCreate(savedInstanceState: Bundle?) {
...
client = Stitch.getInstance(this).conversationClient
attachIncomingCallListener()
callControlBtn.setOnClickListener { callPhone() }
}
private fun attachIncomingCallListener() {
//Listen for incoming calls
client.callEvent().add({ incomingCall ->
logAndShow("answering Call")
//Answer an incoming call
incomingCall.answer(object : RequestHandler<Void> {
override fun onError(apiError: NexmoAPIError) {
logAndShow("Error answer: " + apiError.message)
}
override fun onSuccess(result: Void) {
currentCall = incomingCall
attachCallStateListener(incomingCall)
showHangupButton()
}
})
})
}
private fun attachCallStateListener(incomingCall: Call) {
//Listen for incoming member events in a call
val callEventListener = ResultListener<CallEvent> { message ->
logAndShow("callEvent : state: " + message.state + " .content:" + message.toString())
}
incomingCall.event().add(callEventListener)
}
private fun callPhone() {
val phoneNumber = phoneNumberInput.text.toString()
client.callPhone(phoneNumber, object : RequestHandler<Call> {
override fun onError(apiError: NexmoAPIError) {
logAndShow("Cannot initiate call: " + apiError.message)
}
override fun onSuccess(result: Call) {
currentCall = result
showHangupButton()
when (result.callState) {
Call.CALL_STATE.STARTED -> logAndShow("Started")
Call.CALL_STATE.RINGING -> logAndShow("Ringing")
Call.CALL_STATE.ANSWERED -> logAndShow("Answered")
else -> logAndShow("Error attaching call listener")
}
}
})
}
}Wie Sie sehen können, übernimmt das Nexmo Stitch SDK die harte Arbeit des Platzierens und Beantwortens von Telefonanrufen.
Wie funktioniert das?
Telefonanrufe entgegennehmen
Wenn ein Benutzer die im vorigen Abschnitt gekaufte Nummer anruft, wird Nexmo das NCCO in unserer Antwort-URL nachschlagen https://your-project-name.cloudfunctions.net/answer . Der NCCO wird wie folgt aussehen:
[
{
"action":"talk",
"text":"You are being connected to the Customer."
},
{
"action":"connect",
"endpoint":[
{
"type":"app",
"user":"Customer"
}
]
}
]Dieses NCCO leitet den Anruf an den Benutzer "Kunde" weiter, den wir in unserer App mit dem Stitch SDK erstellt haben. Die App nimmt den Anruf entgegen, indem sie den Call Listener in attachIncomingCallListener() Der Einfachheit halber nehmen wir den Anruf automatisch an, aber Sie könnten eine Benutzeroberfläche und eine Logik implementieren, die es dem Benutzer ermöglicht, den Anruf anzunehmen oder abzulehnen. reject() den Anruf zu beantworten.
Telefonieren Sie
Wenn der Benutzer einen Anruf tätigen möchte, wird dies in der callPhone() Methode. Wenn unsere Methode zum Beispiel so aufgerufen wurde:
client.callPhone("14155550100", callback)Dann wird die client.callPhone(phoneNumber, callback) Methode im Nexmo Stitch Android SDK die Stitch API verwenden, um eine GET eine Anfrage an Ihre Antwort-URL https://your-project-name.cloudfunctions.net/answer mit den folgenden Abfrageparametern:
?from=16625461410\ &to=14155550100\ &conversation_uuid=CON-4e977dab-2abc-42b5-bf64-d468d4763e54\ &uuid=0666edbe58077d826944a7c1913da2b0
Wir können den to Parameter verwenden, um dynamisch einen NCCO zurückzugeben, der Nexmo mitteilt, welche Telefonnummer angerufen werden soll. Die Stitch-API wird die folgende NCCO-Antwort sehen:
[
{
"action":"talk",
"text":"Thank you for calling, you are now being connected."
},
{
"action":"connect",
"from":"12013753230",
"endpoint":[
{
"type":"phone",
"number":"14155550100"
}
]
}
]In diesem Fall ist die from Nummer die Nummer, die wir von Nexmo gemietet und als nexmo.from_number mit Firebase-Konfigurationsvariablen. Der Wert in number Schlüssel im endpoint Array ist die Nummer, die unser Benutzer anrufen möchte.
Probieren Sie es selbst aus
Das Repo für dieses Beispielprojekt enthält den Quellcode sowohl für die Firebase-Funktionen als auch für die Android-Beispiel-App. Klonen Sie das Projekt selbst, um es auszuprobieren!
Was kommt als Nächstes?
Nachdem Sie nun gelernt haben, wie Sie mit Nexmo In-App Voice Anrufe tätigen und entgegennehmen können Nexmo In-App Voice können Sie auch mehr erfahren über In-App Messaging.
Für weitere Details zum Nexmo Stitch Android SDK lesen Sie bitte die SDK-Dokumentation online lesen.
Unser Voice API bietet auch andere Möglichkeiten als nur das Verbinden und Empfangen von Anrufen! Besuchen Sie unsere Dokumentation, um mehr über das Aufzeichnen von Anrufen, das Abspielen von Audio-Streams bei Anrufen und mehr zu erfahren.
