En este documento, se explica cómo integrar y personalizar el SDK en tu aplicación para Android.
Comenzar
El SDK de Headless Mobile para Android te permite integrar las capacidades del centro de contacto de la plataforma de CCAI en tu propia IU de Android integrada.
En lugar de presentar un widget con la marca de CCAI Platform, haz lo siguiente:
Agrega los módulos del SDK de Android de CCAI como dependencias.
Crea tus propias pantallas, flujos y diseños visuales en Kotlin (recomendado) o Java.
Usa el SDK para hacer lo siguiente:
Iniciar y administrar sesiones de chat y voz
Ofrece opciones de correo electrónico, llamadas de voz y desvío.
Admitir acciones inteligentes, archivos adjuntos y flujos posteriores a la sesión (CSAT, encuestas, agente virtual)
CCAI Platform controla la lógica del centro de contacto (enrutamiento, colas, canales, configuración, informes). Eres propietario de toda la experiencia de la app (IU, flujos y desarrollo de la marca).
Si prefieres una IU prediseñada con temas configurables, usa el SDK estándar para dispositivos móviles.
Requisitos y entornos compatibles
En esta sección, se describen los requisitos y los entornos compatibles con el SDK de Headless Mobile para Android.
Requisitos de la plataforma de Android
Se aplican los siguientes requisitos de la plataforma para Android:
Versión mínima de Android: Android 6.0 (nivel de API 23) o versiones posteriores
Compile SDK: 36 (recomendado)
Lenguajes admitidos: Kotlin (recomendado) o Java
Compatibilidad con Java: Java 17 o versiones posteriores
Gradle / Android Studio: Una versión reciente del complemento de Android para Gradle y Android Studio compatible con tu app y la versión del SDK que usas
Versión de Kotlin: 1.6.0 o posterior
Requisitos de la instancia de CCAI Platform
Necesitarás acceder a la configuración para desarrolladores de tu instancia de CCAI Platform para obtener lo siguiente:
Llave de la empresa
Código secreto de la empresa
URL del host: Es el nombre de host de la plataforma de CCAI (por ejemplo, tu_subdominio.ccaiplatform.com).
Estos valores se usan para lo siguiente:
Clave de la empresa y URL del host: En tu app para Android, para inicializar el SDK
Código secreto de la empresa: En tu backend, para firmar tokens web JSON (JWT) que se usan para autenticar a los usuarios.
Redes y permisos
Tu app debe permitir el tráfico saliente a los extremos de la Plataforma de CCAI y a los extremos de los proveedores de voz que hayas configurado.
Los permisos típicos de Android incluyen los siguientes (la lista real puede variar según la versión del SDK y tu conjunto de funciones):
Estado de Internet o de la red: Para todas las comunicaciones del SDK
Micrófono: Para llamadas de voz
Notifications: Para las notificaciones push de Firebase Cloud Messaging (FCM)
Almacenamiento / multimedia: Para archivos adjuntos
Cámara: Para capturar fotos o videos en las acciones inteligentes
Screen capture: Para compartir pantalla (
MediaProjection).
Declara y solicita permisos de tiempo de ejecución según los lineamientos del SO Android.
Notificaciones push
El SDK de Android sin encabezado usa FCM para entregar lo siguiente:
Notificaciones de llamadas entrantes
Determinados mensajes relacionados con las acciones inteligentes y las llamadas
Actualizaciones para ayudar a mantener el estado cuando la app se ejecuta en segundo plano.
Necesitarás:
Un proyecto de Firebase
Un archivo google-services.json válido en el módulo de tu app
Registro y control de tokens de FCM en tu app
IU personalizada de notificaciones y llamadas en tu app
Cómo se adapta el SDK de Android sin encabezado a tu app
El SDK de Headless Mobile para Android se puede ver como tres capas:
Plataforma y SDK de CCAI Platform (administrados por CCAI Platform)
El SDK interactúa de forma segura con la plataforma de CCAI Platform y proporciona lo siguiente:
Autenticación con tokens web JSON (JWT).
Metadatos de enrutamiento de colas y canales (chat, llamadas de voz, correos electrónicos y vínculos de desvío externos)
Administración del estado de la sesión en tiempo real con objetos de servicio (
chatService,queueMenuServicey muchos más).Es la canalización de transporte seguro para acciones inteligentes, archivos adjuntos y uso compartido de pantalla.
Lógica de desvío y evaluación de la jerarquía posterior a la sesión
Tu app para Android (IU y lógica, a cargo tuyo)
Controlas toda la experiencia visual y de navegación:
Puntos de entrada: Por ejemplo, una pestaña de Ayuda o un botón de Comunícate con nosotros.
Menús: Son las formas en que se muestran las filas (por ejemplo, Facturación, Asistencia técnica).
IU en la sesión: Tus burbujas de chat, pantallas de llamadas y controles personalizados.
Qué hace tu app: Llama a las APIs de servicio del SDK para iniciar y finalizar sesiones, observa eventos del SDK con corrutinas y flujos de Kotlin, y controla la navegación de componentes.
Configuración del portal de administrador de CCAI Platform
Tus administradores de la plataforma de CCAI configuran las reglas de participación (horario de atención, canales disponibles, umbrales de tiempo de espera y encuestas). El SDK lee esta configuración y la expone a tu app como datos y eventos sin procesar. Tú decides cómo dibujar esa configuración en la pantalla.
Recupera las credenciales de la empresa
Antes de integrar el SDK, obtén las credenciales de tu instancia de la CCAI Platform:
Accede al portal de administración de CCAI Platform con una cuenta de administrador.
Navega a Configuración > Configuración para desarrolladores.
En Clave y código secreto de la empresa, copia lo siguiente:
Llave de la empresa
Código secreto de la empresa
Anota tu URL de host, el nombre de host de la plataforma de CCAI (por ejemplo,
your_subdomain.ccaiplatform.com).
Qué usarás:
En tu app para Android: Clave de la empresa y URL del host
En tu servidor de backend: Código secreto de la empresa para firmar JWTs para la autenticación del usuario final y datos y contexto personalizados opcionales que usa la Plataforma de CCAI.
Agrega el SDK a tu app para Android
El SDK sin interfaz gráfica usa una arquitectura modular. Instalas el CCAIKit principal junto con los módulos de funciones específicos que requiere tu app (por ejemplo, CCAIChat o CCAIScreenShare).
Agrega el repositorio de Maven de la CCAI
Agrega el repositorio de Maven de la CCAI al settings.gradle.kts (o build.gradle raíz) de tu proyecto:
// settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url = uri("https://sdk.ujet.co/ccaip/android/") }
}
}
Configura el catálogo de versiones de Gradle (recomendado)
Google Cloud recomienda usar un catálogo de versiones de Gradle para administrar las dependencias del SDK. Agrega lo siguiente a tu 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" }
Agrega dependencias
En tu archivo build.gradle.kts a nivel de la app, agrega el SDK principal y los módulos de funciones 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)
}
Si no usas el catálogo de versiones, puedes declarar dependencias directamente:
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
}
Inicialización y configuración
Inicializa el SDK durante el inicio de la app. Debido a la arquitectura modular del SDK, primero inicializa el sistema principal de la plataforma de CCAI y, luego, registra los proveedores de canales específicos (como chat o screen share).
Implementa la interfaz CCAIDelegate
El SDK usa una interfaz CCAIDelegate para las devoluciones de llamada de autenticación. El método clave es una función de suspensión de Kotlin ccaiShouldAuthenticate() que el SDK llama cuando necesita un 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
}
}
}
En el fragmento anterior, se muestra el flujo mínimo de dos pasos (sign → authenticate → return).
Consulta Cómo autenticar usuarios finales y pasar datos personalizados para conocer el contrato de autenticación completo, que incluye lo siguiente:
- cómo firmar el JWT en tu backend
- cómo
authenticate(jwt)lo intercambia por un token de autorización - almacenamiento en caché y la invalidación de tokens
- Ejemplos prácticos con manejo de errores
Inicializa el SDK en la clase de tu aplicación
Inicializa el SDK en tu clase de aplicación personalizada con el 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"
// )
// )
}
}
Referencia de configuración de 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
)
Actualizar AndroidManifest.xml
Asegúrate de que tu clase de aplicación personalizada esté registrada:
<application
android:name=".MainApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.YourApp">
</application>
Servicios disponibles del SDK
Después de la inicialización, puedes acceder a varios servicios a través del 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()
Recuperando la configuración de la empresa
Después de la inicialización, puedes recuperar la configuración a nivel de la empresa con companyService. Esto es útil para completar selectores de idioma, mostrar el nombre de la empresa o leer los detalles de contacto de asistencia antes de que el usuario ingrese a una fila.
// Fetch company details
val company = CCAI.companyService?.get()
// CompanyResponse contains:
// - displayName: String
// - supportEmail: String?
// - languages: List<String>
// - phoneNumber: String?
// ...
Autentica a los usuarios finales y pasa datos personalizados
El SDK de Headless para dispositivos móviles para Android usa tokens web JSON (JWT) para autenticar a los usuarios y pasar de forma segura información contextual al CRM del agente.
Cómo funciona
El SDK usa un flujo de autenticación asíncrono simplificado de dos pasos:
El SDK determina que debe autenticar al usuario.
Llama a tu método
CCAIDelegate(ccaiShouldAuthenticate()), que es una función de suspensión.Tu app firma un JWT de forma remota en tu servidor de backend con tu objeto `Company
Tu app firma un JWT de forma remota en tu servidor de backend con tu
Company Secret Code.Luego, tu app pasa el JWT firmado a
CCAI.authService?.authenticate(jwt)para intercambiarlo por un token de autorización.El token de autorización se devuelve al SDK para completar la conexión.
Implementa CCAIDelegate para la autenticación
Tu app debe implementar la interfaz CCAIDelegate. El SDK llama al primer método de suspensión cuando necesita autenticación.
Interfaz de CCAIDelegate
interface CCAIDelegate {
suspend fun ccaiShouldAuthenticate(): String?
}
Ejemplo de implementación (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
}
}
}
Ejemplo completo con firma de JWT (solo para referencia y pruebas)
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
}
}
}
Cómo pasar datos personalizados al CRM
Si deseas pasar datos contextuales al agente (por ejemplo, el SO, la ubicación o el nivel de la cuenta del usuario actuales), tu backend debe insertar un objeto custom_data en la carga útil del JWT antes de firmarlo.
Cada fragmento de datos personalizados debe tener el formato de un objeto JSON que contenga una etiqueta (lo que ve el agente), un valor y un tipo.
Tipos de datos admitidos
string: Texto estándar (por ejemplo, "Pixel 8 Pro").number: Números enteros o de punto flotante (por ejemplo, 1234 o 99.99).date: Es una marca de tiempo Unix UTC de 13 dígitos que incluye milisegundos (por ejemplo, 1537399655992).url: Es el formato estándar de URL HTTP/HTTPS.boolean: Es un valor estándar verdadero o falso.
Visibilidad del agente: De manera opcional, puedes pasar datos a la plataforma de CCAI que están ocultos para el agente humano, pero disponibles para el enrutamiento o las estadísticas de backend. Para ello, incluye "invisible_to_agent": true en el objeto de datos.
Claves de CRM reservadas
CCAI Platform admite claves reservadas específicas que activan comportamientos integrados en la plataforma, como marcar a un usuario como VIP o advertir a un agente sobre un actor malicioso. Deben tener el formato de tipos boolean y solo se aceptarán si la carga útil se firma con el método seguro JWT.
reserved_verified_customer: Indica si tus sistemas internos autenticaron correctamente a un cliente.reserved_bad_actor: Marca al usuario para el agente como un posible spammer o una cuenta fraudulenta.reserved_repeat_customer: Indica si este cliente se comunicó con el equipo de asistencia al cliente con frecuencia recientemente.
Ejemplo de carga útil con claves 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"
}
}
}
Administra tokens de autenticación
El SDK proporciona métodos para actualizar o borrar manualmente el token de autenticación almacenado en caché:
// 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 carga útil del JWT de datos personalizados
Cuando tu backend crea la carga útil final que se firmará con tu Company
Secret Code, debe seguir estrictamente este esquema. Ten en cuenta las marcas de tiempo obligatorias iat (fecha de emisión) y exp (fecha de vencimiento).
{
"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"
}
}
}
Habilita las notificaciones push
El SDK usa notificaciones push para lo siguiente:
Llamadas entrantes
Determinadas acciones inteligentes y eventos relacionados con llamadas
Mantener el estado cuando la app está en segundo plano
Configuración de Firebase
Crea un proyecto de Firebase o usa uno existente.
Registra tu app para Android y descarga el archivo
google-services.json.Coloca
google-services.jsonen el directorio del módulo de tu app.En tu archivo
build.gradle.ktsa nivel de raíz, agrega el complemento de los servicios de Google:// build.gradle.kts (Project) plugins { id("com.google.gms.google-services") version "4.4.2" apply false }En tu archivo
build.gradle.ktsa nivel de la app, aplica el complemento y agrega dependencias 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") }Sincroniza el proyecto.
Registra el token de FCM con el SDK
Registra el token push de FCM a través de pushNotificationService y reenvía las cargas útiles de datos entrantes de FCM al SDK. Tu app es responsable de renderizar cualquier notificación visible para el cliente o IU durante la llamada.
Implementa onMessageReceived
Si usas FCM, implementa un objeto de escucha en tu clase FirebaseMessagingService para las notificaciones push. Si no se implementan, el servicio no funcionará correctamente.
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)
}
}
}
Implementa onNewToken
También implementa el método onNewToken para controlar las actualizaciones de tokens. Esto garantiza que el SDK de Headless Mobile para Android reciba el token de notificación push más reciente:
class MyFirebaseMessagingService : FirebaseMessagingService() {
// ...
override fun onNewToken(token: String) {
// Fetch the updated token from Firebase and update it in CCAI
CCAI.pushNotificationService?.updatePushToken(token)
}
}
Registra el servicio en AndroidManifest.xml
Agrega el servicio de Firebase Messaging a tu AndroidManifest.xml para que el sistema pueda entregar mensajes push a tu servicio:
<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 del token
En el inicio de la app (después de la inicialización del SDK), registra de forma proactiva el token de FCM actual:
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)
}
}
Control de permisos de notificaciones (Android 13 y versiones posteriores)
En Android 13 (nivel de API 33), las apps mencionadas deben solicitar el permiso de tiempo de ejecución POST_NOTIFICATIONS. El SDK proporciona una utilidad integrada para esto:
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")
}
Llama a este método al principio del ciclo de vida de tu app (por ejemplo, durante la incorporación o el primer lanzamiento) antes de registrar el token de FCM, de modo que se puedan entregar las notificaciones push.