SDK de Mensagens para Clientes do Chat do IVS: Tutorial para Android, parte 1: salas de chat
Esta é a primeira de um tutorial de duas partes. Você aprenderá os fundamentos do trabalho com o SDK de Mensagens do Chat do Amazon IVS ao desenvolver uma aplicação Android totalmente funcional usando a linguagem de programação Kotlin
Antes de iniciar o módulo, dedique alguns minutos para se familiarizar com os pré-requisitos, os principais conceitos por trás dos tokens de chat e o servidor de back-end necessários para criar salas de chat.
Esses tutoriais são criados para desenvolvedores de Android experientes que são iniciantes no SDK de Mensagens para Clientes do Chat do IVS. Você precisará estar familiarizado com a linguagem de programação Kotlin e com a criação de interfaces de usuário na plataforma Android.
Esta primeira parte do tutorial está dividida em várias seções:
Para obter a documentação completa do SDK, comece com o SDK de Mensagens para Clientes do Chat do Amazon IVS (aqui no Guia de usuário do Chat do Amazon IVS) e a Referência de Mensagens para Clientes do Chat: SDK para Android
Pré-requisitos
-
Ter familiaridade com Kotlin e com a criação de aplicações na plataforma Android. Se você não tiver familiaridade com a criação de aplicações para Android, aprenda o básico no guia Crie sua primeira aplicação
para desenvolvedores de Android. -
Ler e compreender completamente os Conceitos básicos do Amazon IVS Chat.
-
Crie um usuário do AWS IAM com os recursos
CreateChatToken
eCreateRoom
definidos em uma política do IAM existente. (Consulte Conceitos básicos do Amazon IVS Chat.) -
Certifique-se de que as chaves secretas/de acesso desse usuário estejam armazenadas em um arquivo de credenciais da AWS. Para obter instruções, consulte o Guia do usuário da AWS CLI (especialmente Configuração e definições do arquivo de credenciais).
-
Crie uma sala de chat e salve seu ARN. Consulte Conceitos básicos do Amazon IVS Chat. (Se você não salvar o ARN, poderá consultá-lo posteriormente com o console ou a API do Chat.)
Configure um servidor local de autenticação/autorização
Seu servidor de back-end será responsável por criar salas de chat e gerar os tokens de chat necessários para que o SDK do Chat do IVS para Android autentique e autorize seus clientes nas salas de chat.
Consulte Criar um token de chat em Introdução ao Amazon IVS Chat. Conforme mostrado no fluxograma, o código do lado do servidor é responsável por criar um token de chat. Isso significa que sua aplicação deve fornecer seu próprio meio de gerar um token de chat solicitando-o da sua aplicação a partir do lado do servidor.
Usamos a estrutura Ktor
Neste momento, esperamos que você tenha as credenciais da AWS configuradas corretamente. Para obter instruções detalhadas, consulte Configurar as credenciais e a região da AWS para o desenvolvimento.
Crie um novo diretório e chame-o de chatterbox
. Nele, crie outro, chamado auth-server
.
A pasta do nosso servidor terá a seguinte estrutura:
- auth-server - src - main - kotlin - com - chatterbox - authserver - Application.kt - resources - application.conf - logback.xml - build.gradle.kts
Observação: é possível copiar e colar este código diretamente nos arquivos referenciados.
Em seguida, adicionaremos todas as dependências e plug-ins necessários para que o servidor de autenticação funcione:
Script de 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") }
Agora, é necessário configurar a funcionalidade de registro em log para o servidor de autenticação. (Para obter mais informações, consulte Configurar 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>
O servidor Ktorapplication.*
no diretório resources
, então adicionaremos isso também. (Para obter mais informações, consulte Configuração em um arquivo
HOCON:
// ./auth-server/src/main/resources/application.conf ktor { deployment { port = 3000 } application { modules = [ com.chatterbox.authserver.ApplicationKt.main ] } }
Por fim, vamos implementar o servidor:
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() ) ) } } }
Crie um projeto de Chatterbox
Para criar um projeto Android, instale e abra o Android Studio
Siga as etapas listadas no guia oficial Criar um projeto
-
Em Escolher o tipo de projeto
, selecione o modelo de projeto Atividade em branco para a aplicação Chatterbox. -
Em Configurar o projeto
, escolha os valores a seguir para os campos de configuração: -
Nome: My App
-
Nome do pacote: com.chatterbox.myapp
-
Salvar localização: direcione para o diretório
chatterbox
criado na etapa anterior -
Linguagem: Kotlin
-
Nível mínimo de API: API 21: Android 5.0 (Lollipop)
-
Após especificar todos os parâmetros de configuração corretamente, a estrutura de arquivos na pasta chatterbox
deve se assemelhar a:
- 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
Agora que temos um projeto Android em funcionamento, é possível adicionar com.amazonaws:ivs-chat-messagingbuild.gradle
. (Para obter mais informações sobre o kit de ferramentas de compilação Gradle
Observação: na parte superior de cada trecho de código, há um caminho para o arquivo em que você deve fazer alterações em seu projeto. O caminho é relativo à raiz do projeto.
No código abaixo, substitua <version>
pelo número da versão atual do SDK do Chat para Android (por exemplo, 1.0.0).
Kotlin:
// ./app/build.gradle plugins { // ... } android { // ... } dependencies { implementation("com.amazonaws:ivs-chat-messaging:<version>") // ... }
Após a nova dependência ser adicionada, execute Sincronizar projeto com arquivos do Gradle no Android Studio para sincronizar o projeto com a nova dependência. (Para obter mais informações, consulte Adicionar dependências de compilação
Para executar o servidor de autenticação (criado na seção anterior) de forma conveniente a partir da raiz do projeto, nós o incluímos como um novo módulo em settings.gradle
. (Para obter mais informações, consulte Como estruturar e criar um componente de software com o Gradle
Script de Kotlin:
// ./settings.gradle // ... rootProject.name = "Chatterbox" include ':app' include ':auth-server'
A partir de agora, como auth-server
está incluso no projeto Android, é possível executar o servidor de autenticação com o seguinte comando da raiz do projeto:
Shell:
./gradlew :auth-server:run
Conecte-se a uma sala de chat e observe as atualizações de conexão
Para abrir uma conexão de sala de chat, usamos o retorno de chamada do ciclo de vida da atividade onCreate()region
e tokenProvider
para instanciar uma conexão de sala.
Observação: a função fetchChatToken
apresentada no trecho abaixo será implementada na próxima seção.
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) } // ... }
Exibir e reagir a mudanças na conexão de uma sala de chat são partes essenciais da criação de uma aplicação de chat como o chatterbox
. Antes de começar a interagir com a sala, é necessário se inscrever em eventos de estado de conexão da sala de chat para obter atualizações.
O 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") } } }
Agora que implementamos o ChatRoomListener
, vamos vinculá-lo à instância da sala:
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 { // ... }
Depois disso, é necessário fornecer a capacidade de ler o estado de conexão da sala. Vamos mantê-lo na propriedadeMainActivity.kt
e inicializá-lo com o estado padrão DISCONNECTED para salas (consulte ChatRoom state
na Referência do SDK do Chat do IVS para AndroidupdateConnectionState
:
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") } } } }
Em seguida, integraremos a função de atualização de estado com a propriedade 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) } } } }
Agora que temos a capacidade de salvar, ouvir e reagir às atualizações de estado do 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) } } // ... } }
Crie um provedor de tokens
É hora de criar uma função responsável pela criação e pelo gerenciamento de tokens de chat na aplicação. Neste exemplo, usamos o cliente HTTP Retrofit para Android
Antes de ser possível enviar qualquer tráfego de rede, é necessário definir uma configuração de segurança de rede para o Android. (Para obter mais informações, consulte Configuração de segurança de redeuser-permission
e o atributo networkSecurityConfig
adicionados, que direcionarão para a nova configuração de segurança de rede. No código abaixo, substitua <version>
pelo número da versão atual do SDK do Chat para Android (por exemplo, 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") }
Declare os domínios 10.0.2.2
e localhost
como confiáveis para começar a trocar mensagens com o back-end:
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>
Em seguida, é necessário adicionar uma nova dependência, em conjunto com a adição do conversor Gson<version>
pelo número da versão atual do SDK do Chat para Android (por exemplo, 1.0.0).
Script de Kotlin:
// ./app/build.gradle dependencies { implementation("com.amazonaws:ivs-chat-messaging:<version>") // ... implementation("com.squareup.retrofit2:retrofit:2.9.0") }
Para recuperar um token de chat, precisamos realizar uma solicitação POST HTTP da aplicação chatterbox
. Definimos a solicitação em uma interface para implementação do Retrofit. (Consulte a documentação do Retrofit
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> }
Agora, com a rede configurada, é o momento de adicionar uma função responsável pela criação e pelo gerenciamento do token de chat. Nós o adicionamos ao MainActivity.kt
, que foi criado automaticamente quando o projeto foi gerado:
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) } }) } }
Próximos Passos
Agora que você estabeleceu uma conexão com a sala de chat, prossiga para a parte 2 deste tutorial para Android: mensagens e eventos.