Client-Messaging-SDK für IVS Chat: Android-Tutorial Teil 1: Chaträume
Hierbei handelt es sich um den ersten Teil eines zweiteiligen Tutorials. Sie werden die Grundlagen der Arbeit mit dem SDK für Amazon IVS Chat Messaging kennenlernen, indem Sie eine voll funktionsfähige Android-Anwendung mithilfe der Kotlin
Bevor Sie das Modul starten, nehmen Sie sich ein paar Minuten Zeit, um sich mit den Voraussetzungen, den wichtigsten Konzepten hinter Chat-Token und dem Backend-Server vertraut zu machen, der für die Erstellung von Chaträumen erforderlich ist.
Diese Tutorials sind für erfahrene Android-Entwickler gedacht, die das IVS Chat Messaging SDK noch nicht kennen. Sie müssen mit der Programmiersprache Kotlin und der Erstellung von Benutzeroberflächen auf der Android-Plattform vertraut sein.
Der vorliegende erste Teil des Tutorials ist in mehrere Abschnitte unterteilt:
Umfassende Informationen zum SDK finden Sie im Client-Messaging-SDK für Amazon IVS Chat (im vorliegenden Benutzerhandbuch zu Amazon IVS Chat) und unter Chat Client Messaging: SDK für Android-Referenz
Voraussetzungen
-
Sie sind vertraut mit Kotlin und der Erstellung von Anwendungen auf der Android-Plattform. Wenn Sie mit der Erstellung von Anwendungen für Android nicht vertraut sind, können Sie die Grundlagen im Leitfaden Erstellen Ihrer ersten App
für Android-Entwickler erlernen. -
Lesen und verstehen Sie Erste Schritte mit Amazon IVS Chat gründlich.
-
Erstellen Sie einen AWS-IAM-Benutzer mit den Fähigkeiten
CreateChatToken
undCreateRoom
, die in einer vorhandenen IAM-Richtlinie definiert sind. (Siehe Erste Schritte mit Amazon IVS Chat). -
Stellen Sie sicher, dass die Geheim-/Zugriffsschlüssel für diesen Benutzer in einer Datei mit den AWS-Anmeldeinformationen gespeichert sind. Entsprechende Anweisungen finden Sie im Benutzerhandbuch zur AWS-CLI (insbesondere unter Einstellungen für Konfigurations- und Anmeldeinformationsdateien).
-
Erstellen Sie einen Chatroom und speichern Sie dessen ARN. Siehe Erste Schritte mit Amazon IVS Chat. (Wenn Sie den ARN nicht speichern, können Sie ihn später über die Konsole oder die Chat-API nachschlagen.)
Einrichten eines lokalen Authentifizierungs-/Autorisierungsservers
Ihr Backend-Server ist sowohl für die Erstellung von Chaträumen als auch für die Generierung der Chat-Token verantwortlich, die das SDK von IVS Chat Android für die Authentifizierung und Autorisierung Ihrer Kunden in Ihren Chaträumen benötigt.
Weitere Informationen finden Sie unter Erstellen eines Chat-Tokens unter Erste Schritte mit Amazon IVS Chat. Wie im dortigen Flussdiagramm gezeigt, erfolgt die Erstellung eines Chat-Tokens in Ihrem serverseitigen Code. Das bedeutet, dass Ihre App eigene Mittel zur Generierung eines Chat-Tokens bereitstellen muss, indem sie ein Token von der serverseitigen Anwendung anfordert.
Mit dem Ktor
Zu diesem Zeitpunkt gehen wir davon aus, dass Sie Ihre AWS-Anmeldeinformationen korrekt eingerichtet haben. Schritt-für-Schritt-Informationen dazu finden Sie unter Einrichten der AWS-Anmeldeinformationen und ‑Region für die Entwicklung.
Erstellen Sie ein neues Verzeichnis mit dem Namen chatterbox
und darin ein weiteres Verzeichnis mit dem Namen auth-server
.
Unser Server-Ordner hat die folgende Struktur:
- auth-server - src - main - kotlin - com - chatterbox - authserver - Application.kt - resources - application.conf - logback.xml - build.gradle.kts
Hinweis: Sie können den Code hier direkt in die referenzierten Dateien kopieren/einfügen.
Als Nächstes fügen wir alle notwendigen Abhängigkeiten und Plugins hinzu, damit unser Authentifizierungsserver funktioniert:
Kotlin-Skript:
// ./auth-server/build.gradle.kts plugins { application kotlin("jvm") kotlin("plugin.serialization").version("1.7.10") } application { mainClass.set("io.ktor.server.netty.EngineMain") } dependencies { implementation("software.amazon.awssdk:ivschat:2.18.1") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.20") implementation("io.ktor:ktor-server-core:2.1.3") implementation("io.ktor:ktor-server-netty:2.1.3") implementation("io.ktor:ktor-server-content-negotiation:2.1.3") implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.3") implementation("ch.qos.logback:logback-classic:1.4.4") }
Jetzt müssen wir die Protokollierungsfunktion für den Authentifizierungsserver einrichten. (Weitere Informationen finden Sie unter Konfigurieren von Logger
XML:
// ./auth-server/src/main/resources/logback.xml <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="trace"> <appender-ref ref="STDOUT"/> </root> <logger name="org.eclipse.jetty" level="INFO"/> <logger name="io.netty" level="INFO"/> </configuration>
Der Ktorapplication.*
-Datei im resources
-Verzeichnis lädt, also fügen wir diese ebenfalls hinzu. (Weitere Informationen finden Sie unter Konfigurierung in einer Datei
HOCON:
// ./auth-server/src/main/resources/application.conf ktor { deployment { port = 3000 } application { modules = [ com.chatterbox.authserver.ApplicationKt.main ] } }
Lassen Sie uns abschließend unseren Server implementieren:
Kotlin:
// ./auth-server/src/main/kotlin/com/chatterbox/authserver/Application.kt package com.chatterbox.authserver import io.ktor.http.* import io.ktor.serialization.kotlinx.json.* import io.ktor.server.application.* import io.ktor.server.plugins.contentnegotiation.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import software.amazon.awssdk.services.ivschat.IvschatClient import software.amazon.awssdk.services.ivschat.model.CreateChatTokenRequest @Serializable data class ChatTokenParams(var userId: String, var roomIdentifier: String) @Serializable data class ChatToken( val token: String, val sessionExpirationTime: String, val tokenExpirationTime: String, ) fun Application.main() { install(ContentNegotiation) { json(Json) } routing { post("/create_chat_token") { val callParameters = call.receive<ChatTokenParams>() val request = CreateChatTokenRequest.builder().roomIdentifier(callParameters.roomIdentifier) .userId(callParameters.userId).build() val token = IvschatClient.create() .createChatToken(request) call.respond( ChatToken( token.token(), token.sessionExpirationTime().toString(), token.tokenExpirationTime().toString() ) ) } } }
Erstellen eines Chatterbox-Projekts
Um ein Android-Projekt zu erstellen, installieren und öffnen Sie das Android Studio
Folgen Sie den Schritten, die in der offiziellen Android-Anleitung zum Erstellen eines Projekts
-
Wählen Sie unter Projekttyp wählen
die Projektvorlage Aktivität leeren für unsere Chatterbox-App aus. -
Wählen Sie unter Projekt konfigurieren
die folgenden Werte für Konfigurationsfelder aus: -
Name: My App
-
Paketname: com.chatterbox.myapp
-
Speicherort: Zeigt auf das im vorherigen Schritt erstellte
chatterbox
-Verzeichnis -
Sprache: Kotlin
-
API-Mindestlevel: API 21: Android 5.0 (Lollipop)
-
Nachdem Sie alle Konfigurationsparameter korrekt angegeben haben, sollte unsere Dateistruktur im chatterbox
-Ordner wie folgt aussehen:
- app - build.gradle ... - gradle - .gitignore - build.gradle - gradle.properties - gradlew - gradlew.bat - local.properties - settings.gradle - auth-server - src - main - kotlin - com - chatterbox - authserver - Application.kt - resources - application.conf - logback.xml - build.gradle.kts
Jetzt, da wir ein funktionierendes Android-Projekt haben, können wir com.amazonaws:ivs-chat-messagingbuild.gradle
-Abhängigkeiten hinzufügen. (Weitere Informationen zum Gradle
Hinweis: Am Anfang jedes Codeausschnitts befindet sich ein Pfad zu der Datei, in der Sie Änderungen an Ihrem Projekt vornehmen sollten. Der Pfad ist relativ zur Root des Projekts.
Ersetzen Sie im folgenden Code <version>
durch die aktuelle Versionsnummer des Chat Android SDKs (z. B. 1.0.0).
Kotlin:
// ./app/build.gradle plugins { // ... } android { // ... } dependencies { implementation("com.amazonaws:ivs-chat-messaging:<version>") // ... }
Nachdem die neue Abhängigkeit hinzugefügt wurde, führen Sie Projekt mit Gradle-Dateien synchronisieren in Android Studio aus, um das Projekt mit der neuen Abhängigkeit zu synchronisieren. (Weitere Informationen finden Sie unter Build-Abhängigkeiten hinzufügen
Um unseren Authentifizierungsserver (der im vorherigen Abschnitt erstellt wurde) bequem vom Projektstammverzeichnis aus ausführen zu können, fügen wir ihn als neues Modul in settings.gradle
hinzu. (Weitere Informationen finden Sie unter Strukturierung und Erstellen einer Softwarekomponente mit Gradle
Kotlin-Skript:
// ./settings.gradle // ... rootProject.name = "Chatterbox" include ':app' include ':auth-server'
Von nun an, da auth-server
im Android-Projekt enthalten ist, können Sie den Authentifizierungsserver mit dem folgenden Befehl aus dem Stammverzeichnis des Projekts starten:
Shell:
./gradlew :auth-server:run
Mit einem Chatraum verbinden und Verbindungsupdates beobachten
Um eine Chatraum-Verbindung zu öffnen, verwenden wir onCreate() activity lifecycle callbackregion
und tokenProvider
bereitstellen, um eine Raumverbindung zu instanziieren.
Hinweis: Die fetchChatToken
-Funktion im folgenden Ausschnitt wird im nächsten Abschnitt implementiert.
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... import androidx.appcompat.app.AppCompatActivity // ... // AWS region of the room that was created in Getting Started with Amazon IVS Chat const val REGION = "us-west-2" class MainActivity : AppCompatActivity() { private var room: ChatRoom? = null // ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create room instance room = ChatRoom(REGION, ::fetchChatToken) } // ... }
Das Anzeigen und Reagieren auf Änderungen in der Verbindung eines Chatraums sind wesentliche Bestandteile einer Chat-App wie chatterbox
. Bevor wir anfangen können, mit dem Raum zu interagieren, müssen wir die Verbindungsstatus-Ereignisse des Chat-Raums abonnieren, um Aktualisierungen zu erhalten.
ChatRoom
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt // ... package com.chatterbox.myapp // ... const val TAG = "IVSChat-App" class MainActivity : AppCompatActivity() { // ... private val roomListener = object : ChatRoomListener { override fun onConnecting(room: ChatRoom) { Log.d(TAG, "onConnecting") } override fun onConnected(room: ChatRoom) { Log.d(TAG, "onConnected") } override fun onDisconnected(room: ChatRoom, reason: DisconnectReason) { Log.d(TAG, "onDisconnected $reason") } override fun onMessageReceived(room: ChatRoom, message: ChatMessage) { Log.d(TAG, "onMessageReceived $message") } override fun onMessageDeleted(room: ChatRoom, event: DeleteMessageEvent) { Log.d(TAG, "onMessageDeleted $event") } override fun onEventReceived(room: ChatRoom, event: ChatEvent) { Log.d(TAG, "onEventReceived $event") } override fun onUserDisconnected(room: ChatRoom, event: DisconnectUserEvent) { Log.d(TAG, "onUserDisconnected $event") } } }
Nun da wir ChatRoomListener
implementiert haben, hängen wir es an unsere Raum-Instance an:
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // Create room instance room = ChatRoom(REGION, ::fetchChatToken).apply { listener = roomListener } } private val roomListener = object : ChatRoomListener { // ... }
Danach müssen wir die Möglichkeit bieten, den Raum-Verbindungsstatus zu lesen. Wir behalten sie in der EigenschaftMainActivity.kt
und initialisieren sie auf den Standardzustand DISCONNECTED für Räume (siehe ChatRoom state
in der Referenz zu IVS Chat Android SDKupdateConnectionState
:
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... enum class ConnectionState { CONNECTED, DISCONNECTED, LOADING } class MainActivity : AppCompatActivity() { private var connectionState = ConnectionState.DISCONNECTED // ... private fun updateConnectionState(state: ConnectionState) { connectionState = state when (state) { ConnectionState.CONNECTED -> { Log.d(TAG, "room connected") } ConnectionState.DISCONNECTED -> { Log.d(TAG, "room disconnected") } ConnectionState.LOADING -> { Log.d(TAG, "room loading") } } } }
Als Nächstes integrieren wir unsere Statusaktualisierungsfunktion in die Eigenschaft ChatRoom.listener
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... class MainActivity : AppCompatActivity() { // ... private val roomListener = object : ChatRoomListener { override fun onConnecting(room: ChatRoom) { Log.d(TAG, "onConnecting") runOnUiThread { updateConnectionState(ConnectionState.LOADING) } } override fun onConnected(room: ChatRoom) { Log.d(TAG, "onConnected") runOnUiThread { updateConnectionState(ConnectionState.CONNECTED) } } override fun onDisconnected(room: ChatRoom, reason: DisconnectReason) { Log.d(TAG, "[${Thread.currentThread().name}] onDisconnected") runOnUiThread { updateConnectionState(ConnectionState.DISCONNECTED) } } } }
Da wir nun die Möglichkeit haben, den ChatRoom
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... enum class ConnectionState { CONNECTED, DISCONNECTED, LOADING } class MainActivity : AppCompatActivity() { private var connectionState = ConnectionState.DISCONNECTED // ... private fun connect() { try { room?.connect() } catch (ex: Exception) { Log.e(TAG, "Error while calling connect()", ex) } } private val roomListener = object : ChatRoomListener { // ... override fun onConnecting(room: ChatRoom) { Log.d(TAG, "onConnecting") runOnUiThread { updateConnectionState(ConnectionState.LOADING) } } override fun onConnected(room: ChatRoom) { Log.d(TAG, "onConnected") runOnUiThread { updateConnectionState(ConnectionState.CONNECTED) } } // ... } }
Erstellen eines Token-Anbieters
Es ist an der Zeit, eine Funktion zu erstellen, die für die Erstellung und Verwaltung von Chat-Token in unserer Anwendung verantwortlich ist. In diesem Beispiel verwenden wir Retrofit-HTTP-Client für Android
Bevor wir Netzwerkverkehr senden können, müssen wir eine Netzwerksicherheitskonfiguration für Android einrichten. (Weitere Informationen finden Sie unter Konfiguration der Netzwerksicherheituser-permission
und das hinzugefügte Attribut networkSecurityConfig
, die auf unsere neue Netzwerksicherheitskonfiguration verweisen. Ersetzen Sie im folgenden Code <version>
durch die aktuelle Versionsnummer des Chat Android SDKs (z. B. 1.0.0).
XML:
// ./app/src/main/AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.chatterbox.myapp"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:fullBackupContent="@xml/backup_rules" android:label="@string/app_name" android:networkSecurityConfig="@xml/network_security_config" // ... // ./app/build.gradle dependencies { implementation("com.amazonaws:ivs-chat-messaging:<version>") // ... implementation("com.squareup.retrofit2:retrofit:2.9.0") }
Deklarieren Sie die Domains 10.0.2.2
und localhost
als vertrauenswürdig, um mit dem Nachrichtenaustausch mit unserem Backend zu beginnen:
XML:
// ./app/src/main/res/xml/network_security_config.xml <?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">10.0.2.2</domain> <domain includeSubdomains="true">localhost</domain> </domain-config> </network-security-config>
Als Nächstes müssen wir eine neue Abhängigkeit sowie Gson converter addition<version>
durch die aktuelle Versionsnummer des Chat Android SDKs (z. B. 1.0.0).
Kotlin-Skript:
// ./app/build.gradle dependencies { implementation("com.amazonaws:ivs-chat-messaging:<version>") // ... implementation("com.squareup.retrofit2:retrofit:2.9.0") }
Um ein Chat-Token abzurufen, müssen wir eine POST-HTTP-Anfrage von unserer chatterbox
-App aus stellen. Wir definieren die Anfrage in einer Schnittstelle, die Retrofit implementieren soll. (Siehe Retrofit-Dokumentation
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/network/ApiService.kt package com.chatterbox.myapp.network // ... import androidx.annotation.Keep import com.amazonaws.ivs.chat.messaging.ChatToken import retrofit2.Call import retrofit2.http.Body import retrofit2.http.POST data class CreateTokenParams(var userId: String, var roomIdentifier: String) interface ApiService { @POST("create_chat_token") fun createChatToken(@Body params: CreateTokenParams): Call<ChatToken> }
Jetzt, da das Netzwerk eingerichtet ist, ist es an der Zeit, eine Funktion hinzuzufügen, die für die Erstellung und Verwaltung unseres Chat-Tokens verantwortlich ist. Wir fügen sie zu MainActivity.kt
hinzu, das bei der Generierung des Projekts automatisch erstellt wurde:
Kotlin:
// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import com.amazonaws.ivs.chat.messaging.* import com.chatterbox.myapp.network.CreateTokenParams import com.chatterbox.myapp.network.RetrofitFactory import retrofit2.Call import java.io.IOException import retrofit2.Callback import retrofit2.Response // custom tag for logging purposes const val TAG = "IVSChat-App" // any ID to be associated with auth token const val USER_ID = "test user id" // ID of the room the app wants to access. Must be an ARN. See Amazon Resource Names(ARNs) const val ROOM_ID = "arn:aws:..." // AWS region of the room that was created in Getting Started with Amazon IVS Chat const val REGION = "us-west-2" class MainActivity : AppCompatActivity() { private val service = RetrofitFactory.makeRetrofitService() private lateinit var userId: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } private fun fetchChatToken(callback: ChatTokenCallback) { val params = CreateTokenParams(userId, ROOM_ID) service.createChatToken(params).enqueue(object : Callback<ChatToken> { override fun onResponse(call: Call<ChatToken>, response: Response<ChatToken>) { val token = response.body() if (token == null) { Log.e(TAG, "Received empty token response") callback.onFailure(IOException("Empty token response")) return } Log.d(TAG, "Received token response $token") callback.onSuccess(token) } override fun onFailure(call: Call<ChatToken>, throwable: Throwable) { Log.e(TAG, "Failed to fetch token", throwable) callback.onFailure(throwable) } }) } }
Nächste Schritte
Nachdem Sie nun eine Chatraum-Verbindung hergestellt haben, fahren Sie mit Teil 2 dieses Android-Tutorials fort: Nachrichten und Ereignisse.