SDK headless para dispositivos móveis para Android: como começar

Este documento explica como integrar e personalizar o SDK no seu app Android.

Primeiros passos

O SDK para dispositivos móveis sem interface para Android permite integrar os recursos de central de atendimento da plataforma CCAI à sua própria interface do Android.

Em vez de apresentar um widget com a marca da CCAI Platform, 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:

    • Inicie e gerencie sessões de chat e voz.

    • Ofereça opções de e-mail, ligação e desvio.

    • Oferecer suporte a ações inteligentes, anexos e fluxos pós-sessão (CSAT, pesquisas, agente virtual).

A plataforma CCAI lida com a lógica da central de atendimento (roteamento, filas, canais, configuração, relatórios). Você é responsável por toda a experiência no app (UI, fluxos e branding).

Se você preferir uma UI pré-criada com temas configuráveis, use o SDK padrão para dispositivos móveis.

Requisitos e ambientes compatíveis

Nesta seção, descrevemos os requisitos e os ambientes compatíveis com o SDK para dispositivos móveis sem interface 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+

  • 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: 2.0 ou mais recente

Requisitos de instância da plataforma CCAI

Você vai precisar acessar as configurações de desenvolvedor da instância da plataforma CCAI para receber:

  • 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 back-end para assinar JSON Web Tokens (JWT) usados para autenticar usuários.

Rede e permissões

Seu app precisa permitir o tráfego de saída para os endpoints da plataforma CCAI e todos 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 ligações.

  • Notificações: somente se você usar notificações push (consulte Notificações push abaixo).

  • Armazenamento / mídia: somente se o app ler fotos, vídeos ou arquivos do armazenamento compartilhado diretamente. Os arquivos do app e o seletor de fotos do sistema não precisam de permissão.

  • Câmera: para capturar 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 sem interface usa o FCM para enviar:

  • 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 google-services.json válido no módulo do app.

  • Processamento e registro de tokens do FCM no app.

  • Notificação personalizada e UI de chamada no app.

Como o SDK do Android headless se encaixa no seu app

O SDK para Dispositivos Móveis Headless para Android pode ser visto como três camadas:

Plataforma e SDK da CCAI Platform (processados pela CCAI Platform)

O SDK interage de forma segura com a 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 desvio externo).

  • Gerenciamento de estado de sessão em tempo real usando objetos de serviço (chatService, queueMenuService e muito mais).

  • O pipeline de transporte seguro para ações inteligentes, anexos de arquivos e compartilhamento de tela.

  • Lógica de desvio e avaliação de hierarquia pós-sessão.

Seu app Android (UI e lógica, processados 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 diálogo, telas de chamada e controles personalizados.

  • O que o app faz: chama as APIs de serviço do SDK para iniciar e encerrar sessões, observa eventos do SDK usando corrotinas e fluxo do Kotlin e orienta a navegação de componentes.

Configuração do portal de administração 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 brutos e eventos. Você decide como desenhar essa configuração na tela.

Recuperar credenciais da empresa

Antes de integrar o SDK, consiga as credenciais da sua instância da plataforma CCAI:

  1. Faça login no portal de administração da CCAI Platform com uma conta de administrador.

  2. Acesse Configurações > Configurações do desenvolvedor.

  3. Em Chave da empresa e código secreto, copie:

    • Chave da empresa

    • Código secreto da empresa

  4. Anote o URL do host, que é o nome do host da plataforma CCAI (por exemplo, your_subdomain.ccaiplatform.com).

Você usará:

  • No app Android: Chave da empresa e URL do host.

  • No 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 app Android

O SDK Headless usa uma arquitetura modular. Instale o CCAIKit principal 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 (ou build.gradle raiz) do seu projeto:

// 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 o uso de um catálogo de versões do Gradle para gerenciar dependências do SDK. Adicione o seguinte ao gradle/libs.versions.toml:

[versions]
ccaiVersion = "3.5.0"

[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 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 o lançamento do app. Devido à arquitetura modular do SDK, inicialize primeiro o sistema principal da CCAI Platform e, em seguida, 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.CCAI
import com.ccaiplatform.ccaikit.CCAIDelegate
import kotlinx.coroutines.CancellationException

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: CancellationException) {
            throw e
        } catch (e: Throwable) {
            // Includes NetworkError, which extends Error rather than Exception
            null // Return null to signal authentication failure
        }
    }
}

O snippet anterior mostra o fluxo mínimo de duas etapas (assinar → autenticar → retornar).

Consulte Autenticar usuários finais e transmitir dados personalizados para ver o contrato de autenticação completo, incluindo:

  • como assinar o JWT no back-end,
  • como o authenticate(jwt) o troca por um token de autenticação,
  • armazenamento em cache e invalidação de tokens, além de
  • exemplos práticos com tratamento de erros.

Inicializar o SDK na classe do aplicativo

Inicialize o SDK na sua classe Application 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.ccaiscreenshare.initializeScreenShare  // If using screen share
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",
            delegate = delegate            // Your CCAIDelegate implementation
        )

        // 2. Initialize the Core SDK
        CCAI.initialize(
            context = this,
            options = initOptions
        )

        // Optional: set the SDK language (ISO 639 code). See Languages and localization
        // in Headless Mobile SDK v3 for Android: Advanced Topics, Localization, and Post-Session Flows.
        CCAI.languageService?.languageCode = "en"

        // 3. Initialize Chat - minimal
        CCAI.initializeChat(context = this)

        // Initialize Chat - with optional configuration
        // val chatOptions = ChatOptions(
        //     webFormHandler = null,                // Optional suspend handler that renders web forms in your own UI
        //     downloadTranscriptVisibility = DownloadTranscriptVisibility.SHOW_ALL
        // )
        // To set a chat greeting, pass Chat(greeting = ...) in the ChatRequest
        // 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_SCREEN_SHARE_LICENSE_KEY",   // License Key (Settings > Developer Settings > Screen Share)
        //         domain = "https://your-screen-share-domain.example.com" // Optional: the Screen Share Domain URL
        //     )
        // )
    }
}

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

Verifique se a classe de aplicativo personalizada está registrada:

<application
    android:name=".MainApplication"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.YourApp">
</application>

Serviços do SDK disponíveis

Após a inicialização, é possível acessar vários serviços pelo objeto singleton CCAI:

val authService = CCAI.authService
val companyService = CCAI.companyService
val queueMenuService = CCAI.queueMenuService
val languageService = CCAI.languageService
val pushNotificationService = CCAI.pushNotificationService
val smartActionService = CCAI.smartActionService
val endUserService = CCAI.endUserService
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()

Buscar 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, exibir 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<LanguageSetting>? (each with lang, name, and enabled)
// - phoneNumber: String?
// ...

Autenticar usuários finais e transmitir dados do cliente

O SDK para dispositivos móveis sem interface para Android usa JSON Web Tokens (JWT) para autenticar usuários e transmitir informações contextuais com segurança para o CRM do agente.

Como funciona

O SDK usa um fluxo de autenticação assíncrona simplificado em duas etapas:

  1. O SDK determina que precisa autenticar o usuário.

  2. Ele chama o método CCAIDelegate, ccaiShouldAuthenticate(), que é uma função de suspensão.

  3. Seu app chama o servidor de back-end para receber um JWT assinado.

  4. Em seguida, o app transmite o JWT assinado para CCAI.authService?.authenticate(jwt) para trocá-lo por um token de autenticação.

  5. 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 de suspensão quando precisa de autenticação.

Interface CCAIDelegate

interface CCAIDelegate {
    suspend fun ccaiShouldAuthenticate(): String?
}

Exemplo de implementação (Kotlin)

class MyCCAIDelegate : 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: CancellationException) {
            throw e
        } catch (e: Throwable) {
            // Includes NetworkError, which extends Error rather than Exception
            null
        }
    }
}

Transmitir dados do cliente para o CRM

Se você quiser transmitir dados de contexto ao agente (por exemplo, o SO do dispositivo atual do usuário, a localização ou o nível da conta), seu back-end precisará injetar um objeto custom_data no payload do JWT antes de assiná-lo.

Cada dado personalizado precisa ser formatado como um objeto JSON que contém 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 flutuantes (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 de URL HTTP/HTTPS padrão.

  • boolean: valor padrão verdadeiro ou falso.

Visibilidade do agente: é possível transmitir dados para a plataforma CCAI que ficam ocultos para o 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 CCAI Platform é 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 mal-intencionado. 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 pelos seus sistemas internos.

  • reserved_bad_actor: sinaliza o usuário para o agente como um possível criador de spam 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 armazenado 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 do JWT de dados do cliente

Quando o back-end cria o payload final a ser assinado com seu Company Secret Code, ele precisa seguir estritamente esse esquema. Observe os carimbos de data/hora obrigatórios iat (emitido em) e exp (expiração).

{
  "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:

  • Chamadas recebidas.

  • Determinadas ações inteligentes e eventos relacionados a chamadas.

  • Manter o estado quando o app está em segundo plano.

Configuração do Firebase

  1. Crie ou use um projeto do Firebase.

  2. Registre seu app Android e faça o download do arquivo google-services.json.

  3. Coloque google-services.json no diretório do módulo do app.

  4. No arquivo build.gradle.kts no 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
    }
    
  5. No build.gradle.kts do app, aplique o plug-in e adicione as dependências Firebase:

    // 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")
    }
    
  6. Sincronize o projeto.

Registrar o token do FCM com o SDK

Registre o token de push do FCM pelo 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 durante a 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 para dispositivos móveis sem interface 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 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 atual do FCM:

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

Tratamento de permissões de notificação (Android 13 ou mais recente)

No Android 13 (nível 33 da API) e versões mais recentes, o app precisa da permissão de execução POST_NOTIFICATIONS para mostrar notificações. O SDK oferece um utilitário integrado para solicitar essa permissão:

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 enviadas.