Kit SDK de messagerie client Chat IVS : coroutines Kotlin, partie 1 : salles de chat - Amazon IVS

Kit SDK de messagerie client Chat IVS : coroutines Kotlin, partie 1 : salles de chat

Il s'agit de la première partie d'un didacticiel en deux volets. Vous apprendrez les bases de l'utilisation du SDK de messagerie du Chat Amazon IVS en créant une application Android entièrement fonctionnelle à l'aide du langage de programmation Kotlin et des coroutines. Nous appelons l'application Chatterbox.

Avant de commencer le module, prenez quelques minutes pour vous familiariser avec les prérequis, les concepts clés des jetons de discussion et le serveur principal nécessaire à la création de salles de chat.

Ces didacticiels sont conçus pour les développeurs Android expérimentés qui découvrent le SDK de messagerie d'IVS Chat. Vous devrez être à l'aise avec le langage de programmation Kotlin et la création d'interfaces utilisateur sur la plateforme Android.

Cette première partie du didacticiel est divisée en plusieurs sections :

Pour une documentation complète sur le SDK, commencez par le SDK de messagerie client Chat Amazon IVS (ici dans le Guide de l'utilisateur Chat Amazon IVS) et la Messagerie client de chat : référence du SDK pour Android (sur GitHub).

Prérequis

Configurer un serveur d'authentification/d'autorisation local

Votre serveur backend est chargé à la fois de créer des salles de chat et de générer les jetons de chat nécessaires au SDK de chat IVS pour Android pour authentifier et autoriser vos clients à accéder à vos salles de chat.

Consultez la section Créer un jeton de chat dans Mise en route avec Chat Amazon IVS. Comme le montre l'organigramme, votre code côté serveur est chargée de créer un jeton de chat. Cela signifie que votre application doit fournir ses propres moyens de générer un jeton de chat en demandant un jeton à votre application côté serveur.

Nous utilisons l'infrastructure Ktor pour créer un serveur local en direct qui gère la création de jetons de chat à l'aide de votre environnement AWS local.

À ce stade, nous nous attendons à ce que vos informations d'identification AWS soient correctement configurées. Pour savoir comment procéder, consultez Configuration des informations d'identification AWS temporaires et de la région AWS pour le développement.

Créez un nouveau répertoire et appelez-le chatterbox et, à l'intérieur, un autre, appelé auth-server.

La structure de notre serveur sera la suivante :

- auth-server - src - main - kotlin - com - chatterbox - authserver - Application.kt - resources - application.conf - logback.xml - build.gradle.kts

Remarque : vous pouvez directement copier/coller le code ici dans les fichiers référencés.

Ensuite, nous ajoutons toutes les dépendances et tous les plugins nécessaires au fonctionnement de notre serveur d'authentification :

Script Kotlin :

// ./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") }

Nous devons maintenant configurer la fonctionnalité de journalisation pour le serveur d'authentification. (Pour plus d'informations, veuillez consulter Configure 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>

Le serveur Ktor nécessite des paramètres de configuration, qu'il charge automatiquement à partir du fichier application.* du répertoire resources. Nous les ajoutons donc également. (Pour plus d'informations, consultez Configuration in a file.)

HOCON :

// ./auth-server/src/main/resources/application.conf ktor { deployment { port = 3000 } application { modules = [ com.chatterbox.authserver.ApplicationKt.main ] } }

Enfin, implémentons notre serveur :

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() ) ) } } }

Créer un projet Chatterbox

Pour créer un projet Android, installez et ouvrez Android Studio.

Suivez les étapes répertoriées dans le guide officiel Android Créer un projet.

  • Dans Choisir le type de projet, choisissez le modèle de projet Empty Activity (Activité vide) pour notre application Chatterbox.

  • Dans Configurer votre projet, choisissez les valeurs suivantes pour les champs de configuration :

    • Nom : My App

    • Nom de package : com.chatterbox.myapp

    • Emplacement d'enregistrement : pointez sur le répertoire chatterbox créé à l'étape précédente

    • Langage : Kotlin

    • Niveau d'API minimum : API 21 : Android 5.0 (Lollipop)

Après avoir correctement spécifié tous les paramètres de configuration, la structure de nos fichiers dans le dossier chatterbox doit ressembler à ce qui suit :

- 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

Maintenant que nous avons un projet Android fonctionnel, nous pouvons ajouter com.amazonaws:ivs-chat-messaging et org.jetbrains.kotlinx:kotlinx-coroutines-core à nos dépendances build.gradle. (Pour plus d'informations sur la boîte à outils de génération Gradle, voir Configurer votre build.)

Remarque : en haut de chaque extrait de code, il y a un chemin vers le fichier dans lequel vous devez apporter des modifications à votre projet. Le chemin est relatif par rapport à la racine du projet.

Kotlin :

// ./app/build.gradle plugins { // ... } android { // ... } dependencies { implementation 'com.amazonaws:ivs-chat-messaging:1.1.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4' // ... }

Une fois la nouvelle dépendance ajoutée, exécutez Synchroniser le projet avec les fichiers Gradle dans Android Studio pour synchroniser le projet avec la nouvelle dépendance. (Pour de plus amples informations, veuillez consulter la section Ajouter des dépendances de build.)

Pour exécuter facilement notre serveur d'authentification (créé dans la section précédente) à partir de la racine du projet, nous l'incluons en tant que nouveau module dans settings.gradle. (Pour plus d'informations, voir Structurer et construire un composant de logiciel avec Gradle.)

Script Kotlin :

// ./settings.gradle // ... rootProject.name = "My App" include ':app' include ':auth-server'

À présent, comme auth-server est inclus dans le projet Android, vous pouvez exécuter le serveur d'authentification à l'aide de la commande suivante depuis la racine du projet :

Shell :

./gradlew :auth-server:run

Se connecter à une salle de chat et observer les mises à jour de la connexion

Pour ouvrir une connexion à une salle de chat, nous utilisons le rappel du cycle de vie de l'activité onCreate(), qui se déclenche lorsque l'activité est créée pour la première fois. Le constructeur ChatRoom nous oblige à fournir region et tokenProvider pour lancer une connexion à une salle.

Remarque : la fonction fetchChatToken présentée dans l'extrait ci-dessous sera implémentée dans la section suivante.

Kotlin :

// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... // 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) } // ... }

L'affichage et la réaction aux modifications de la connexion à une salle de chat est un élément essentiel pour la création d'une application de chat comme chatterbox. Avant de pouvoir commencer à interagir avec la salle, nous devons nous abonner aux événements relatifs à l'état de connexion de la salle de chat pour obtenir des mises à jour.

Dans le SDK Chat pour la coroutine, ChatRoom attend de nous que nous gérions les événements du cycle de vie des salles dans Flux. Pour l'instant, les fonctions enregistreront uniquement les messages de confirmation, lorsqu'ils sont invoqués :

Kotlin :

// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... const val TAG = "Chatterbox-MyApp" class MainActivity : AppCompatActivity() { // ... override fun onCreate(savedInstanceState: Bundle?) { // ... // Create room instance room = ChatRoom(REGION, ::fetchChatToken).apply { lifecycleScope.launch { stateChanges().collect { state -> Log.d(TAG, "state change to $state") } } lifecycleScope.launch { receivedMessages().collect { message -> Log.d(TAG, "messageReceived $message") } } lifecycleScope.launch { receivedEvents().collect { event -> Log.d(TAG, "eventReceived $event") } } lifecycleScope.launch { deletedMessages().collect { event -> Log.d(TAG, "messageDeleted $event") } } lifecycleScope.launch { disconnectedUsers().collect { event -> Log.d(TAG, "userDisconnected $event") } } } } }

Ensuite, nous devons fournir la possibilité de lire l'état de la connexion à la salle. Nous le conserverons dans la propriété MainActivity.kt et l'initialiserons à l'état DÉCONNECTÉ par défaut pour les salles (voir ChatRoom state dans la référence du SDK IVS Chat pour Android). Pour pouvoir maintenir l'état local à jour, nous devons implémenter une fonction de mise à jour de l'état ; appelons-le updateConnectionState :

Kotlin :

// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... class MainActivity : AppCompatActivity() { private var connectionState = ChatRoom.State.DISCONNECTED // ... private fun updateConnectionState(state: ChatRoom.State) { connectionState = state when (state) { ChatRoom.State.CONNECTED -> { Log.d(TAG, "room connected") } ChatRoom.State.DISCONNECTED -> { Log.d(TAG, "room disconnected") } ChatRoom.State.CONNECTING -> { Log.d(TAG, "room connecting") } } }

Ensuite, nous intégrons notre fonction de mise à jour de l'état à la propriété Chatroom.Listener :

Kotlin :

// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... class MainActivity : AppCompatActivity() { // ... override fun onCreate(savedInstanceState: Bundle?) { // ... // Create room instance room = ChatRoom(REGION, ::fetchChatToken).apply { lifecycleScope.launch { stateChanges().collect { state -> Log.d(TAG, "state change to $state") updateConnectionState(state) } } // ... } } }

Maintenant que nous sommes en mesure d'enregistrer, d'écouter et de réagir aux mises à jour d'état de ChatRoom, il est temps d'initialiser une connexion :

Kotlin :

// ./app/src/main/java/com/chatterbox/myapp/MainActivity.kt package com.chatterbox.myapp // ... class MainActivity : AppCompatActivity() { // ... private fun connect() { try { room?.connect() } catch (ex: Exception) { Log.e(TAG, "Error while calling connect()", ex) } } // ... }

Créer un fournisseur de jetons

Il est temps de créer une fonction chargée de créer et de gérer des jetons de chat dans notre application. Dans cet exemple, nous utilisons le client HTTP Retrofit pour Android.

Avant de pouvoir envoyer du trafic réseau, nous devons configurer une configuration de sécurité réseau pour Android. Pour plus d'informations, consultez Network security configuration.) Nous commençons par ajouter des autorisations réseau au fichier App Manifest. Notez la balise user-permission et l'attribut networkSecurityConfig ajoutés, qui indiqueront notre nouvelle configuration de sécurité réseau. Dans le code ci-dessous, remplacez <version> par le numéro de version actuel du SDK de chat pour Android (par exemple, 1.1.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") implementation("com.squareup.retrofit2:converter-gson:2.9.0") }

Déclarez votre adresse IP locale, par exemple 10.0.2.2 et les domaines localhost comme fiables, pour commencer à échanger des messages avec notre backend :

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>

Ensuite, nous devons ajouter une nouvelle dépendance, ainsi que l'ajout d'un convertisseur Gson pour analyser les réponses HTTP. Dans le code ci-dessous, remplacez <version> par le numéro de version actuel du SDK de chat pour Android (par exemple, 1.1.0).

Script Kotlin :

// ./app/build.gradle dependencies { implementation("com.amazonaws:ivs-chat-messaging:<version>") // ... implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") }

Pour récupérer un jeton de chat, nous devons effectuer une requête HTTP POST depuis notre application chatterbox. Nous définissons la demande dans une interface que Retrofit doit implémenter. (Voir la documentation de Retrofit (français non garanti). Familiarisez-vous également avec la spécification de l’opération CreateChatToken.)

Kotlin :

// ./app/src/main/java/com/chatterbox/myapp/network/ApiService.kt package com.chatterbox.myapp.network 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> } // ./app/src/main/java/com/chatterbox/myapp/network/RetrofitFactory.kt package com.chatterbox.myapp.network import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory object RetrofitFactory { private const val BASE_URL = "http://10.0.2.2:3000" fun makeRetrofitService(): ApiService { return Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build().create(ApiService::class.java) } }

Maintenant que le réseau est configuré, il est temps d'ajouter une fonction chargée de créer et de gérer notre jeton de chat. Nous l'ajoutons à MainActivity.kt, qui a été automatiquement créé lors de la génération du projet :

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 androidx.lifecycle.lifecycleScope import kotlinx.coroutines.launch import com.amazonaws.ivs.chat.messaging.* import com.amazonaws.ivs.chat.messaging.coroutines.* 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 = "Chatterbox-MyApp" // 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 var userId: String = USER_ID // ... 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) } }) } }

Étapes suivantes

Maintenant que vous avez établi une connexion à la salle de chat, passez à la seconde partie de ce didacticiel Coroutines Kotlin, Messages et événements.