Este documento explica como integrar e personalizar o SDK no seu aplicativo Android.
Primeiros passos
O SDK móvel sem interface gráfica para Android permite integrar os recursos da central de atendimento da plataforma CCAI à sua própria interface do Android.
Em vez de apresentar um widget com a marca da plataforma CCAI, você:
Adicione os módulos do SDK do Android do CCAI como dependências.
Crie suas próprias telas, fluxos e design visual em Kotlin (recomendado) ou Java.
Use o SDK para:
Iniciar e gerenciar sessões de chat e de voz.
Ofereça opções de e-mail, ligação e redirecionamento.
Suporte a ações inteligentes, anexos e fluxos pós-sessão (CSAT, pesquisas, agente virtual).
A CCAI Platform processa a lógica da central de atendimento (roteamento, filas, canais, configuração, relatórios). Você é o proprietário de toda a experiência no app (UI, fluxos e branding).
Se você preferir uma UI pré-criada com temas configuráveis, use o SDK móvel padrão.
Requisitos e ambientes compatíveis
Esta seção descreve os requisitos e os ambientes compatíveis com o SDK Headless Mobile para Android.
Requisitos da plataforma Android
Os seguintes requisitos de plataforma se aplicam ao Android:
Versão mínima do Android: Android 6.0 (nível 23 da API) ou mais recente
SDK de compilação: 36 (recomendado)
Linguagens compatíveis: Kotlin (recomendado) ou Java
Compatibilidade com Java: Java 17 ou mais recente
Gradle / Android Studio: uma versão recente do Plug-in do Android para Gradle e do Android Studio compatível com seu app e a versão do SDK que você está usando
Versão do Kotlin: 1.6.0 ou mais recente
Requisitos da instância da plataforma CCAI
Você precisa ter acesso às configurações de desenvolvedor da instância da plataforma CCAI para obter:
Chave da empresa
Código secreto da empresa
URL do host: é o nome do host da plataforma CCAI (por exemplo, your_subdomain.ccaiplatform.com)
Esses valores são usados para:
Chave da empresa e URL do host no app Android para inicializar o SDK.
Código secreto da empresa: no seu back-end para assinar JSON Web Tokens (JWT) usados para autenticar usuários.
Rede e permissões
O app precisa permitir o tráfego de saída para os endpoints da plataforma CCAI e para os endpoints de provedores de voz que você configurou.
As permissões típicas do Android incluem (a lista real pode variar de acordo com a versão do SDK e seu conjunto de atributos):
Estado da Internet / rede: para todas as comunicações do SDK.
Microfone: para chamadas de voz.
Notificações: para notificações push do Firebase Cloud Messaging (FCM).
Armazenamento / mídia: para anexos.
Câmera: para captura de fotos ou vídeos em ações inteligentes.
Captura de tela: para compartilhamento de tela (
MediaProjection).
Declare e solicite permissões de execução de acordo com as diretrizes do SO Android.
Notificações push
O SDK do Android Headless usa o FCM para oferecer:
Notificações de chamadas recebidas.
Algumas mensagens relacionadas a chamadas e ações inteligentes.
Atualizações para ajudar a manter o estado quando o app está em segundo plano.
Você precisará dos seguintes itens:
um projeto do Firebase;
Um arquivo google-services.json válido no módulo do app.
Processamento e registro de tokens do FCM no seu app.
Notificação personalizada e interface da ligação no seu app.
Como o SDK do Android headless se encaixa no seu app
O SDK Headless Mobile para Android pode ser visto como três camadas:
Plataforma e SDK da CCAI Platform (processados pela CCAI Platform)
O SDK interage com segurança com a plataforma CCAI Platform e oferece:
Autenticação com JSON Web Tokens (JWT).
Metadados de roteamento de fila e canal (chat, ligação, e-mail, links de redirecionamento externo).
Gerenciamento de estado de sessão em tempo real usando objetos de serviço (
chatService,queueMenuServicee muito mais).O pipeline de transporte seguro para ações inteligentes, anexos de arquivos e compartilhamento de tela.
Lógica de evasão e avaliação de hierarquia pós-sessão.
Seu app Android (UI e lógica, processadas por você)
Você controla toda a experiência visual e de navegação:
Pontos de entrada: por exemplo, uma guia Ajuda ou um botão Entre em contato.
Menus: como você mostra as filas (por exemplo, Faturamento, Suporte técnico).
Interface na sessão: seus balões de chat, telas de chamada e controles personalizados.
O que o app faz: chama APIs de serviço do SDK para iniciar e encerrar sessões, observa eventos do SDK usando corrotinas e fluxos do Kotlin e impulsiona a navegação de componentes.
Configuração do portal de administrador da plataforma CCAI
Os administradores da Plataforma CCAI configuram as regras de engajamento (horário de funcionamento, canais disponíveis, limites de tempo de espera e pesquisas). O SDK lê essa configuração e a expõe ao app como dados e eventos brutos. Você decide como desenhar essa configuração na tela.
Recuperar credenciais da empresa
Antes de integrar o SDK, extraia as credenciais da sua instância da plataforma CCAI:
Faça login no portal de administração da CCAI Platform com uma conta de administrador.
Acesse Configurações > Configurações do desenvolvedor.
Em Chave da empresa e código secreto, copie:
Chave da empresa
Código secreto da empresa
Anote o URL do host, que é o nome do host da plataforma CCAI (por exemplo,
your_subdomain.ccaiplatform.com).
Você usará:
No seu app Android: Chave da empresa e URL do host.
No seu servidor de back-end: código secreto da empresa para assinar JWTs para autenticação do usuário final e dados e contexto personalizados opcionais usados pela plataforma da CCAI.
Adicionar o SDK ao seu app Android
O SDK Headless usa uma arquitetura modular. Você instala o CCAIKit principal
junto com os módulos de recursos específicos que o app exige (por exemplo,
CCAIChat ou CCAIScreenShare).
Adicionar o repositório Maven da CCAI
Adicione o repositório Maven da CCAI ao settings.gradle.kts do projeto (ou build.gradle raiz):
// settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url = uri("https://sdk.ujet.co/ccaip/android/") }
}
}
Configurar o catálogo de versões do Gradle (recomendado)
OGoogle Cloud recomenda usar um catálogo de versões do Gradle para gerenciar dependências do SDK. Adicione o seguinte ao seu gradle/libs.versions.toml:
[versions]
ccaiVersion = "3.3.1"
[libraries]
ccai-kit = { group = "com.ccaiplatform.android", name = "CCAIKit", version.ref = "ccaiVersion" }
ccai-chat = { group = "com.ccaiplatform.android", name = "CCAIChat", version.ref = "ccaiVersion" }
ccai-chat-red = { group = "com.ccaiplatform.android", name = "CCAIChatRed", version.ref = "ccaiVersion" }
ccai-call = { group = "com.ccaiplatform.android", name = "CCAICall", version.ref = "ccaiVersion" }
ccai-call-red = { group = "com.ccaiplatform.android", name = "CCAICallRed", version.ref = "ccaiVersion" }
ccai-screenshare = { group = "com.ccaiplatform.android", name = "CCAIScreenShare", version.ref = "ccaiVersion" }
Adicionar dependências
No build.gradle.kts do nível do app, adicione o SDK principal e os módulos de recursos específicos:
// app/build.gradle.kts
android {
compileSdk = 36
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}
dependencies {
// 1. Core (always required)
implementation(libs.ccai.kit)
// 2. Chat (required for chat sessions)
implementation(libs.ccai.chat)
implementation(libs.ccai.chat.red) // media layer paired with CCAIChat
// 3. Voice (required for instant calls, voicemail, and scheduled calls)
implementation(libs.ccai.call)
implementation(libs.ccai.call.red) // media/transport layer paired with CCAICall
// 4. Screen Share (optional)
// implementation(libs.ccai.screenshare)
}
Se você não estiver usando o catálogo de versões, declare as dependências diretamente:
val ccaiVersion = "3.3.1"
dependencies {
implementation("com.ccaiplatform.android:CCAIKit:$ccaiVersion")
implementation("com.ccaiplatform.android:CCAIChat:$ccaiVersion")
implementation("com.ccaiplatform.android:CCAIChatRed:$ccaiVersion")
implementation("com.ccaiplatform.android:CCAICall:$ccaiVersion") // Voice calls
implementation("com.ccaiplatform.android:CCAICallRed:$ccaiVersion") // Twilio VoIP backend
implementation("com.ccaiplatform.android:CCAIScreenShare:$ccaiVersion") // Optional, for screen share
}
Inicialização e configuração
Inicialize o SDK durante a inicialização do app. Devido à arquitetura modular do SDK,
inicialize primeiro o sistema principal da plataforma CCAI e depois registre os
provedores de canais específicos (como chat ou screen share).
Implementar a interface CCAIDelegate
O SDK usa uma interface CCAIDelegate para callbacks de autenticação. O método
principal é uma função de suspensão do Kotlin ccaiShouldAuthenticate() que o SDK
chama quando precisa de um JWT.
import com.ccaiplatform.ccaikit.CCAIDelegate
class MyCCAIDelegate : CCAIDelegate {
/**
* Called by the SDK when it needs a signed JWT for authentication.
* This is a suspend function - you can make network calls here.
*
* @return The auth token returned by `authService.authenticate(jwt)`,
* or null on failure. This is what the SDK expects - not the raw JWT.
*/
override suspend fun ccaiShouldAuthenticate(): String? {
return try {
// 1. Call your backend server to get a signed JWT
val jwt = MyBackendApi.getSignedJwt() ?: return null
// 2. Exchange the JWT for an auth token using authService - this is
// what the SDK expects to be returned (not the raw JWT).
CCAI.authService?.authenticate(jwt)
} catch (e: Exception) {
null // Return null to signal authentication failure
}
}
}
O snippet anterior mostra o fluxo mínimo de duas etapas (sign → authenticate → return).
Consulte Autenticar usuários finais e transmitir dados personalizados para conferir o contrato de autenticação completo, incluindo:
- como assinar o JWT no back-end,
- como o
authenticate(jwt)troca por um token de autenticação, - armazenamento em cache e invalidação de tokens;
- exemplos práticos com tratamento de erros.
Inicializar o SDK na classe do aplicativo
Inicialize o SDK na sua classe de aplicativo personalizada usando o objeto singleton
CCAI:
import android.app.Application
import com.ccaiplatform.ccaikit.CCAI
import com.ccaiplatform.ccaikit.InitOptions
import com.ccaiplatform.ccaichat.initializeChat
import com.ccaiplatform.ccaichat.model.ChatOptions
import com.ccaiplatform.ccaicall.initializeCall
import com.ccaiplatform.ccaikit.initializeScreenShare
import com.ccaiplatform.ccaikit.models.screenShare.ScreenShareOptions
class MainApplication : Application() {
private val delegate = MyCCAIDelegate()
override fun onCreate() {
super.onCreate()
// 1. Build InitOptions
val initOptions = InitOptions(
key = "YOUR_COMPANY_KEY",
urlHost = "your_subdomain.ccaiplatform.com",
languageCode = "en", // Optional: ISO 639 code
delegate = delegate // Your delegate implementation
)
// 2. Initialize the core SDK
CCAI.initialize(
context = this,
options = initOptions
)
// 3. Initialize chat (minimal)
CCAI.initializeChat(context = this)
// Initialize chat (with optional configuration)
// val chatOptions = ChatOptions(
// webFormInterface = null, // Implement to intercept and render custom web forms within your own UI
// downloadTranscriptVisibility = DownloadTranscriptVisibility.SHOW_ALL,
// greeting = "Hello! How can I help you?"
// )
// CCAI.initializeChat(
// context = this,
// options = chatOptions
// )
// 4. Initialize call (required whenever your app uses voice or scheduled calls)
CCAI.initializeCall(context = this)
// 5. Initialize screen share (optional)
// CCAI.initializeScreenShare(
// context = this,
// options = ScreenShareOptions(
// key = "YOUR_COMPANY_KEY",
// domain = "your_subdomain.ccaiplatform.com"
// )
// )
}
}
Referência de configuração do InitOptions
data class InitOptions(
/// The company key used for authentication
var key: String,
/// The host URL for CCAI platform (for example, "my-unique-instance.uc1.ccaiplatform.com")
var urlHost: String,
/// The preferred language code for localization (defaults to "en")
var languageCode: String? = "en",
/// Listener that handles authentication
var delegate: CCAIDelegate? = null,
/// Whether to cache the authentication token (defaults to true)
var cacheAuthToken: Boolean = true
)
Atualizar AndroidManifest.xml
Confira se a classe do aplicativo personalizado está registrada:
<application
android:name=".MainApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.YourApp">
</application>
Serviços de SDK disponíveis
Depois da inicialização, você pode acessar vários serviços usando o objeto singleton CCAI:
val authService = CCAI.authService
val companyService = CCAI.companyService
val queueMenuService = CCAI.queueMenuService
val optionsService = CCAI.optionsService
val languageService = CCAI.languageService
val pushNotificationService = CCAI.pushNotificationService
val chatService = CCAI.chatService // Only available after initializeChat()
val screenShareService = CCAI.screenShareService // Only available after initializeScreenShare()
val rateService = CCAI.rateService // For CSAT ratings and survey submission
val callService = CCAI.callService // Only available after initializeCall()
Buscando configuração da empresa
Após a inicialização, é possível buscar a configuração no nível da empresa usando o
companyService. Isso é útil para preencher seletores de idioma, mostrar o nome da empresa ou ler os detalhes de contato do suporte antes que o usuário entre em uma fila.
// Fetch company details
val company = CCAI.companyService?.get()
// CompanyResponse contains:
// - displayName: String
// - supportEmail: String?
// - languages: List<String>
// - phoneNumber: String?
// ...
Autenticar usuários finais e transmitir dados personalizados
O SDK Headless Mobile para Android usa JSON Web Tokens (JWT) para autenticar usuários e transmitir informações contextuais com segurança ao CRM do agente.
Como funciona
O SDK usa um fluxo de autenticação assíncrono simplificado de duas etapas:
O SDK determina que precisa autenticar o usuário.
Ele chama o método
CCAIDelegate,ccaiShouldAuthenticate(), que é uma função de suspensão.Seu app assina um JWT remotamente no servidor de back-end usando o `Company
O app assina um JWT remotamente no servidor de back-end usando seu
Company Secret Code.Em seguida, o app transmite o JWT assinado para
CCAI.authService?.authenticate(jwt)para trocá-lo por um token de autenticação.O token de autenticação é retornado ao SDK para concluir a conexão.
Implementar o CCAIDelegate para autenticação
O app precisa implementar a interface CCAIDelegate. O SDK chama o primeiro método
suspend quando precisa de autenticação.
Interface CCAIDelegate
interface CCAIDelegate {
suspend fun ccaiShouldAuthenticate(): String?
}
Exemplo de implementação (Kotlin)
class CCAIDelegate : CCAIDelegate {
override suspend fun ccaiShouldAuthenticate(): String? {
// 1. Sign JWT remotely on your backend server
val jwt = signJWTRemotely() ?: return null
// 2. Authenticate JWT using authService to get an auth token
return try {
CCAI.authService?.authenticate(jwt)
} catch (e: Exception) {
null
}
}
}
Exemplo completo com assinatura JWT (apenas para referência e teste)
class AuthController : CCAIDelegate {
override suspend fun ccaiShouldAuthenticate(): String? {
// First, sign JWT with company secret (do this on your backend in production)
val jwt = Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS384, companySecret?.encodeToByteArray())
.compact()
// Then authenticate JWT using authService to get an auth token
return try {
CCAI.authService?.authenticate(jwt)
} catch (e: Exception) {
null
}
}
}
Transmitir dados personalizados ao CRM
Se você quiser transmitir dados contextuais ao agente (por exemplo, o SO do dispositivo atual, a localização ou o nível da conta do usuário), seu back-end precisará injetar um objeto custom_data no payload do JWT antes de assiná-lo.
Cada parte de dados personalizados precisa ser formatada como um objeto JSON que contenha um
rótulo (o que o agente vê), um valor e um tipo.
Tipos de dados compatíveis
string: texto padrão (por exemplo, "Pixel 8 Pro").number: números inteiros ou de ponto flutuante (por exemplo, 1234 ou 99,99).date: um carimbo de data/hora Unix UTC de 13 dígitos, incluindo milissegundos (por exemplo, 1537399655992).url: formato padrão de URL HTTP/HTTPS.boolean: valor padrão verdadeiro ou falso.
Visibilidade do agente: é possível transmitir dados para a plataforma CCAI
que ficam ocultos do agente humano, mas disponíveis para roteamento ou
análise de back-end. Para fazer isso, inclua "invisible_to_agent": true no
objeto de dados.
Chaves de CRM reservadas
A plataforma CCAI é compatível com chaves reservadas específicas que acionam comportamentos integrados na plataforma, como sinalizar um usuário como VIP ou avisar um agente sobre um usuário de má-fé. Eles precisam ser formatados como tipos boolean e só serão aceitos se o payload for assinado usando o método seguro JWT.
reserved_verified_customer: indica se um cliente foi autenticado com sucesso pelos seus sistemas internos.reserved_bad_actor: sinaliza o usuário para o agente como um possível spammer ou conta fraudulenta.reserved_repeat_customer: indica se o cliente entrou em contato com o suporte com frequência recentemente.
Exemplo de payload com chaves reservadas
{
"iat": 1537399656,
"exp": 1537400256,
"custom_data": {
"reserved_verified_customer": {
"label": "Verified Customer",
"value": true,
"type": "boolean"
},
"reserved_bad_actor": {
"label": "Bad Actor",
"value": false,
"type": "boolean"
},
"reserved_repeat_customer": {
"label": "Repeat Customer",
"value": false,
"type": "boolean"
}
}
}
Gerenciar tokens de autenticação
O SDK oferece métodos para atualizar ou limpar manualmente o token de autenticação em cache:
// Set a new auth token
CCAI.authService?.updateAuthToken("new_auth_token")
// Clear the current token (for example, on user logout)
CCAI.authService?.updateAuthToken(null)
Esquema de payload JWT de dados personalizados
Quando o back-end constrói o payload final a ser assinado com seu Company
Secret Code, ele precisa seguir estritamente este esquema. Observe os carimbos de data/hora obrigatórios iat (emitido em) e exp (validade).
{
"iat": 1537399656,
"exp": 1537400256,
"custom_data": {
"os_version": {
"label": "OS Version",
"value": "14.0",
"type": "string"
},
"membership_tier": {
"label": "Membership Tier",
"value": "Platinum",
"type": "string"
},
"ssn_last_four": {
"label": "SSN",
"value": "1234",
"type": "string",
"invisible_to_agent": true
},
"reserved_verified_customer": {
"label": "Verified Customer",
"value": true,
"type": "boolean"
}
}
}
Ativar notificações push
O SDK usa notificações push para:
Ligações recebidas.
Algumas ações inteligentes e eventos relacionados a chamadas.
Manter o estado quando o app está em segundo plano.
Configuração do Firebase
Crie ou use um projeto do Firebase.
Registre seu app Android e faça o download do arquivo
google-services.json.Coloque
google-services.jsonno diretório do módulo do app.No
build.gradle.ktsno nível raiz, adicione o plug-in dos Serviços do Google:// build.gradle.kts (Project) plugins { id("com.google.gms.google-services") version "4.4.2" apply false }No arquivo
build.gradle.ktsno nível do app, aplique o plug-in e adicione dependências deFirebase:// app/build.gradle.kts plugins { id("com.google.gms.google-services") } dependencies { // Firebase BoM for version management implementation(platform("com.google.firebase:firebase-bom:33.5.1")) implementation("com.google.firebase:firebase-messaging") }Sincronize o projeto.
Registrar o token do FCM com o SDK
Registre o token push do FCM usando o pushNotificationService e encaminhe
os payloads de dados do FCM recebidos para o SDK. Seu app é responsável por renderizar qualquer
notificação voltada ao cliente ou UI de chamada.
Implementar onMessageReceived
Se você estiver usando o FCM, implemente um listener na classe FirebaseMessagingService
para notificações push. Se eles não forem implementados, o serviço não vai funcionar corretamente.
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.ccaiplatform.ccaikit.CCAI
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MyFirebaseMessagingService : FirebaseMessagingService() {
private val scope = CoroutineScope(Dispatchers.IO)
override fun onMessageReceived(remoteMessage: RemoteMessage) {
scope.launch {
// Forward CCAI platform push notifications to the SDK.
CCAI.pushNotificationService?.handlePushNotification(remoteMessage.data)
// Render any customer-facing notification UI in your own app code.
MyNotificationRenderer.showIfNeeded(application, remoteMessage.data)
}
}
}
Implementar onNewToken
Implemente também o método onNewToken para processar atualizações de token. Isso garante
que o SDK móvel sem interface gráfica para Android receba o token
de notificação push mais recente:
class MyFirebaseMessagingService : FirebaseMessagingService() {
// ...
override fun onNewToken(token: String) {
// Fetch the updated token from Firebase and update it in CCAI
CCAI.pushNotificationService?.updatePushToken(token)
}
}
Registre o serviço em AndroidManifest.xml.
Adicione o serviço de mensagens do Firebase ao seu AndroidManifest.xml para que o sistema
possa enviar mensagens push ao seu serviço:
<application>
<service
android:name=".firebase.MyFirebaseMessagingService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
Registro inicial do token
Na inicialização do app (após a inicialização do SDK), registre proativamente o token do FCM atual:
import com.google.firebase.messaging.FirebaseMessaging
// In your Application.onCreate(), after CCAI.initialize()
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
val token = task.result
CCAI.pushNotificationService?.updatePushToken(token)
}
}
Processamento de permissões de notificação (Android 13 ou mais recente)
No Android 13 (nível 33 da API), os apps mencionados precisam solicitar a permissão de
execução POST_NOTIFICATIONS. O SDK oferece um utilitário integrado para
isso:
import com.ccaiplatform.ccaikit.util.PermissionUtil
// Request notification permissions from the user
PermissionUtil.requestPermissionsForNotifications(activity)
// Check if permissions have been granted
val isGranted = PermissionUtil.isPermissionsForNotificationsGranted(context)
if (isGranted) {
Log.d("CCAI", "Push notifications permitted")
}
Chame isso no início do ciclo de vida do app (por exemplo, durante a integração ou o primeiro lançamento) antes de registrar o token do FCM para que as notificações push possam ser entregues.