

# SDK de Mensagens para Clientes do Chat do IVS: Tutorial para Android, parte 1: salas de chat
<a name="chat-sdk-android-tutorial-chat-rooms"></a>

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](https://kotlinlang.org/). Chamamos a aplicação de *Chatterbox*.

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 backend 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:

1. [Configure um servidor local de autenticação/autorização](#chat-android-rooms-auth-server)

1. [Crie um projeto de Chatterbox](#chat-android-rooms-chatterbox)

1. [Conecte-se a uma sala de chat e observe as atualizações de conexão](#chat-android-rooms-connect-state)

1. [Crie um provedor de tokens](#chat-android-rooms-token-provider)

1. [Próximas etapas](#chat-android-rooms-next-steps)

Para obter a documentação completa do SDK, comece com o [SDK de Mensagens para Clientes do Chat do Amazon IVS](chat-sdk.md) (aqui no *Guia de usuário do Chat do Amazon IVS*) e a [Referência de Mensagens para Clientes do Chat: SDK para Android](https://aws.github.io/amazon-ivs-chat-messaging-sdk-android/1.0.0/) (no Github).

## Pré-requisitos
<a name="chat-android-rooms-prerequisites"></a>
+ 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](https://developer.android.com/codelabs/basic-android-kotlin-compose-first-app#0) para desenvolvedores de Android.
+ Ler e compreender completamente os [Conceitos básicos do Amazon IVS Chat](getting-started-chat.md).
+ Crie um usuário do AWS IAM com os recursos `CreateChatToken` e `CreateRoom` definidos em uma política do IAM existente. (Consulte [Conceitos básicos do Amazon IVS Chat](getting-started-chat.md).)
+ 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](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) (especialmente [Configuração e definições do arquivo de credenciais](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)).
+ Crie uma sala de chat e salve seu ARN. Consulte [Conceitos básicos do Amazon IVS Chat](getting-started-chat.md). (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
<a name="chat-android-rooms-auth-server"></a>

Seu servidor de backend 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](getting-started-chat-auth.md) 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](https://ktor.io/) para criar um servidor local ativo que gerencia a criação de tokens de chat usando seu ambiente local da AWS.

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](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html).

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](https://ktor.io/docs/logging.html#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>
```

O servidor [Ktor](https://ktor.io/docs/welcome.html) requer definições de configuração, que são carregadas automaticamente do arquivo `application.*` no diretório `resources`, então adicionaremos isso também. (Para obter mais informações, consulte [Configuração em um arquivo](https://ktor.io/docs/configurations.html#configuration-file).)

**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
<a name="chat-android-rooms-chatterbox"></a>

Para criar um projeto Android, instale e abra o [Android Studio](https://developer.android.com/studio).

Siga as etapas listadas no [guia oficial Criar um projeto](https://developer.android.com/studio/projects/create-project) do Android.
+ Em [Escolher o tipo de projeto](https://developer.android.com/studio/projects/create-project), selecione o modelo de projeto **Atividade em branco** para a aplicação Chatterbox.
+ Em [Configurar o projeto](https://developer.android.com/studio/projects/create-project#configure), 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-messaging](https://mvnrepository.com/artifact/com.amazonaws/ivs-chat-messaging) às dependências `build.gradle`. (Para obter mais informações sobre o kit de ferramentas de compilação [Gradle](https://gradle.org/), consulte [Configurar sua compilação](https://developer.android.com/build).)

**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](https://developer.android.com/build/dependencies).)

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](https://docs.gradle.org/current/userguide/multi_project_builds.html).)

**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
<a name="chat-android-rooms-connect-state"></a>

Para abrir uma conexão de sala de chat, usamos o [retorno de chamada do ciclo de vida da atividade onCreate()](https://developer.android.com/guide/components/activities/activity-lifecycle), que é acionado quando a atividade é criada pela primeira vez. O [construtor do ChatRoom](https://aws.github.io/amazon-ivs-chat-messaging-sdk-android/1.0.0/-amazon%20-i-v-s%20-chat%20-messaging%20-s-d-k%20for%20-android/com.amazonaws.ivs.chat.messaging/-chat-room/index.html) exige que forneçamos `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](#chat-android-rooms-token-provider).

**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](https://aws.github.io/amazon-ivs-chat-messaging-sdk-android/1.0.0/-amazon%20-i-v-s%20-chat%20-messaging%20-s-d-k%20for%20-android/com.amazonaws.ivs.chat.messaging/-chat-room/index.html) espera que vinculemos uma implementação da [interface ChatRoomListener](https://aws.github.io/amazon-ivs-chat-messaging-sdk-android/1.0.0/-amazon%20-i-v-s%20-chat%20-messaging%20-s-d-k%20for%20-android/com.amazonaws.ivs.chat.messaging/-chat-room/listener.html) para a geração de eventos de ciclo de vida. Por enquanto, as funções do receptor registrarão em log somente mensagens de confirmação, quando invocadas:

**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 [propriedade](https://kotlinlang.org/docs/properties.html) `MainActivity.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 Android](https://aws.github.io/amazon-ivs-chat-messaging-sdk-android/latest/)). Para ser possível manter o estado local atualizado, é necessário implementar uma função de atualização de estado. Vamos chamá-la de `updateConnectionState`:

**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](https://aws.github.io/amazon-ivs-chat-messaging-sdk-android/1.0.0/-amazon%20-i-v-s%20-chat%20-messaging%20-s-d-k%20for%20-android/com.amazonaws.ivs.chat.messaging/-chat-room/listener.html):

**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](https://aws.github.io/amazon-ivs-chat-messaging-sdk-android/1.0.0/-amazon%20-i-v-s%20-chat%20-messaging%20-s-d-k%20for%20-android/com.amazonaws.ivs.chat.messaging/-chat-room/index.html), é o momento de inicializar uma conexão:

**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
<a name="chat-android-rooms-token-provider"></a>

É 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](https://square.github.io/retrofit/).

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 rede](https://developer.android.com/privacy-and-security/security-config).) Começamos adicionando permissões de rede ao arquivo [Manifesto da aplicação](https://developer.android.com/guide/topics/manifest/manifest-intro). Observe a etiqueta `user-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 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>
```

Em seguida, é necessário adicionar uma nova dependência, em conjunto com a [adição do conversor Gson](https://github.com/square/retrofit/tree/trunk/retrofit-converters/gson) para analisar as respostas HTTP. *No código abaixo, substitua `<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](https://square.github.io/retrofit/). Familiarize-se também com a especificação da operação [CreateChatToken](https://docs.aws.amazon.com//ivs/latest/ChatAPIReference/API_CreateChatToken.html#API_CreateChatToken_RequestBody).

**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](#chat-android-rooms-chatterbox):

**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óximas etapas
<a name="chat-android-rooms-next-steps"></a>

Agora que você estabeleceu uma conexão com a sala de chat, prossiga para a parte 2 deste tutorial para Android: [mensagens e eventos](chat-sdk-android-tutorial-messages-events.md).