本文档介绍了如何在 Android 应用中集成和自定义 SDK。
开始使用
借助适用于 Android 的无头移动 SDK,您可以将 CCAI Platform 的联络中心功能集成到自己的内置 Android 界面中。
您无需展示 CCAI Platform 品牌的 widget,而是:
将 CCAI Android SDK 模块添加为依赖项。
使用 Kotlin(推荐)或 Java 构建您自己的界面、流程和视觉设计。
使用 SDK 可执行以下操作:
开始和管理聊天会话和语音会话。
提供电子邮件、语音通话和分流选项。
支持智能操作、附件和会话后流程(客户满意度 [CSAT]、调查问卷、虚拟客服)。
CCAI Platform 可处理联络中心逻辑(路由、队列、渠道、配置、报告)。您拥有完整的应用体验(界面、流程和品牌)。
如果您希望使用具有可配置主题的预构建界面,请使用标准移动 SDK。
要求和支持的环境
本部分介绍了适用于 Android 的无头移动 SDK 的要求和支持的环境。
Android 平台要求
以下平台要求适用于 Android:
最低 Android 版本:Android 6.0(API 级别 23)或更高版本
编译 SDK:36(推荐)
支持的语言:Kotlin(推荐)或 Java
Java 兼容性:Java 17 及更高版本
Gradle / Android Studio:与您的应用和所用 SDK 版本兼容的最新 Android Gradle 插件和 Android Studio 版本
Kotlin 版本:1.6.0 或更高版本
CCAI Platform 实例要求
您需要访问 CCAI 平台实例的开发者设置,才能获取以下信息:
公司密钥
公司密令
主机网址 - CCAI 平台的主机名(例如 your_subdomain.ccaiplatform.com)
这些值用于:
公司密钥和宿主网址 - 在 Android 应用中初始化 SDK。
公司密钥 - 在后端用于对 JSON Web 令牌 (JWT) 进行签名,以对用户进行身份验证。
网络和权限
您的应用必须允许出站流量流向 CCAI 平台端点以及您配置的任何语音提供商端点。
典型的 Android 权限包括(实际列表可能因 SDK 版本和功能集而异):
互联网 / 网络状态:用于所有 SDK 通信。
麦克风:用于语音通话。
通知:用于 Firebase Cloud Messaging (FCM) 推送通知。
存储空间 / 媒体:用于附件。
相机:用于在智能操作中拍摄照片或视频。
屏幕截图:用于屏幕共享 (
MediaProjection)。
根据 Android OS 指南声明和请求运行时权限。
推送通知
无头 Android SDK 使用 FCM 来传送:
来电通知。
某些智能操作和通话相关消息。
更新以帮助在应用进入后台时保持状态。
您需要有:
Firebase 项目。
应用模块中包含有效的 google-services.json。
应用中的 FCM 令牌处理和注册。
应用中的自定义通知和通话中界面。
无头 Android SDK 如何融入您的应用
Android 版无头移动 SDK 可以视为三个层:
CCAI Platform 平台和 SDK(由 CCAI Platform 处理)
该 SDK 可与 CCAI Platform 平台安全地互动,并提供以下功能:
使用 JSON Web 令牌 (JWT) 进行身份验证。
队列和渠道路由元数据(即时通讯、语音通话、电子邮件、外部改道链接)。
使用服务对象(
chatService、queueMenuService等)进行实时会话状态管理。用于智能操作、文件附件和屏幕共享的安全传输流水线。
分流逻辑和会话后层次结构评估。
您的 Android 应用(界面和逻辑 - 由您处理)
您可以控制整个视觉和导航体验:
入口点:例如帮助标签页或与我们联系按钮。
菜单:您如何显示队列(例如结算、技术支持)。
会话内界面:自定义聊天气泡、通话界面和控件。
应用的功能:调用 SDK 服务 API 来开始和结束会话,使用 Kotlin 协程和 Flow 观察 SDK 事件,并驱动组件导航。
CCAI 平台管理门户配置
CCAI 平台管理员配置互动规则(营业时间、可用渠道、等待时间阈值和调查问卷)。SDK 会读取此配置,并以原始数据和事件的形式将其公开给您的应用。您可以决定如何在屏幕上绘制该配置。
检索公司凭据
在集成 SDK 之前,请从 CCAI 平台实例获取凭据:
使用管理员账号登录 CCAI Platform 管理员门户。
依次前往设置 > 开发者设置。
在公司密钥和密钥令牌下方,复制以下内容:
公司密钥
公司密令
记下您的主机网址,即 CCAI 平台的主机名(例如
your_subdomain.ccaiplatform.com)。
您将使用:
在 Android 应用中:公司密钥和主机网址。
在后端服务器中:用于对 JWT 进行签名的公司密钥代码,以进行最终用户身份验证,以及 CCAI 平台使用的可选自定义数据和上下文。
将 SDK 添加到您的 Android 应用
Headless SDK 采用模块化架构。您需要安装核心 CCAIKit 以及应用所需的特定功能模块(例如 CCAIChat 或 CCAIScreenShare)。
添加 CCAI Maven 制品库
将 CCAI Maven 制品库添加到项目的 settings.gradle.kts(或根级 build.gradle)中:
// settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url = uri("https://sdk.ujet.co/ccaip/android/") }
}
}
配置 Gradle 版本目录(推荐)
Google Cloud 建议使用 Gradle 版本目录来管理 SDK 依赖项。将以下内容添加到 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" }
添加依赖项
在应用级 build.gradle.kts 中,添加核心 SDK 和特定功能模块:
// 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)
}
如果您未使用版本目录,可以直接声明依赖项:
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
}
初始化和设置
在应用启动期间初始化 SDK。由于 SDK 采用模块化架构,因此请先初始化核心 CCAI 平台系统,然后注册特定的渠道提供商(例如 chat 或 screen share)。
实现 CCAIDelegate 接口
该 SDK 使用 CCAIDelegate 接口进行身份验证回调。关键方法是 Kotlin 挂起函数 ccaiShouldAuthenticate(),SDK 在需要 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
}
}
}
上述代码段展示了最简单的两步流程(签名 → 身份验证 → 返回)。
如需了解完整的身份验证合约,请参阅对最终用户进行身份验证并传递自定义数据,其中包括:
- 如何在后端对 JWT 进行签名,
authenticate(jwt)如何将其换成身份验证令牌,- 令牌缓存和失效,以及
- 包含错误处理的示例。
在应用类中初始化 SDK
使用 CCAI singleton 对象在自定义应用类中初始化 SDK:
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"
// )
// )
}
}
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
)
更新“AndroidManifest.xml”
确保已注册自定义应用类:
<application
android:name=".MainApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.YourApp">
</application>
可用的 SDK 服务
初始化后,您可以通过 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()
正在提取公司配置
初始化后,您可以使用 companyService 获取公司级配置。这对于填充语言选择器、显示公司名称或在用户进入队列之前读取支持联系详情非常有用。
// Fetch company details
val company = CCAI.companyService?.get()
// CompanyResponse contains:
// - displayName: String
// - supportEmail: String?
// - languages: List<String>
// - phoneNumber: String?
// ...
对最终用户进行身份验证并传递自定义数据
适用于 Android 的 Headless Mobile SDK 使用 JSON Web 令牌 (JWT) 对用户进行身份验证,并安全地将情境信息传递给客服人员的 CRM。
工作原理
该 SDK 使用简化的两步异步身份验证流程:
SDK 确定需要对用户进行身份验证。
它会调用您的
CCAIDelegate方法 -ccaiShouldAuthenticate()- 这是一个挂起函数。您的应用使用您的 `Company
您的应用使用
Company Secret Code在后端服务器上远程签署 JWT。然后,您的应用会将已签名的 JWT 传递给
CCAI.authService?.authenticate(jwt),以换取身份验证令牌。身份验证令牌会返回到 SDK 以完成连接。
实现用于身份验证的 CCAIDelegate
您的应用必须实现 CCAIDelegate 接口。当 SDK 需要进行身份验证时,会调用第一个 suspend 方法。
CCAIDelegate 接口
interface CCAIDelegate {
suspend fun ccaiShouldAuthenticate(): String?
}
实现示例 (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
}
}
}
包含 JWT 签名的完整示例(仅供参考和测试)
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
}
}
}
将自定义数据传递给 CRM
如果您想将情境数据(例如用户的当前设备操作系统、位置信息或账号层级)传递给代理,您的后端必须在对 JWT 载荷进行签名之前,将 custom_data 对象注入到该载荷中。
每条自定义数据都必须采用 JSON 对象的格式,其中包含标签(客服人员看到的内容)、值和类型。
支持的数据类型
string:标准文本(例如“Pixel 8 Pro”)。number:整数或浮点数(例如 1234 或 99.99)。date:一个 13 位数的 UTC Unix 时间戳,包含毫秒(例如 1537399655992)。url:标准 HTTP/HTTPS 网址格式。boolean:标准 true 或 false 值。
客服可见性:您可以选择性地将数据传递给 CCAI 平台,这些数据对人工客服隐藏,但可用于路由或后端分析。为此,请在数据对象中添加 "invisible_to_agent": true。
预留的 CRM 键
CCAI Platform 支持特定的预留键,这些键可触发平台中的内置行为,例如将用户标记为 VIP 或向客服人员发出有关作恶方的警告。这些必须采用 boolean 类型格式,并且只有在使用安全的 JWT 方法对载荷进行签名时才会被接受。
reserved_verified_customer:表示客户是否已通过您的内部系统成功完成身份验证。reserved_bad_actor:向代理标记用户,表明其可能是垃圾信息发送者或欺诈性账号。reserved_repeat_customer:表示相应客户最近是否经常与支持人员联系。
包含预留键的载荷示例
{
"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"
}
}
}
管理身份验证令牌
SDK 提供了一些方法来手动更新或清除缓存的身份验证令牌:
// Set a new auth token
CCAI.authService?.updateAuthToken("new_auth_token")
// Clear the current token (for example, on user logout)
CCAI.authService?.updateAuthToken(null)
自定义数据 JWT 载荷架构
当后端构建要使用 Company
Secret Code 签名的最终载荷时,必须严格遵循此架构。请注意强制性 iat(签发时间)和 exp(失效时间)时间戳。
{
"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"
}
}
}
启用推送通知
该 SDK 使用推送通知来执行以下操作:
来电。
某些智能操作和与通话相关的事件。
在应用处于后台时保持状态。
Firebase 设置
创建或使用现有 Firebase 项目。
注册您的 Android 应用并下载
google-services.json文件。将
google-services.json放在应用模块目录中。在根级
build.gradle.kts中,添加 Google 服务插件:// build.gradle.kts (Project) plugins { id("com.google.gms.google-services") version "4.4.2" apply false }在应用级
build.gradle.kts中,应用插件并添加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") }同步项目。
向 SDK 注册 FCM 令牌
通过 pushNotificationService 注册 FCM 推送令牌,并将传入的 FCM 数据载荷转发到 SDK。您的应用负责渲染面向客户的任何通知或通话中界面。
实现 onMessageReceived
如果您使用的是 FCM,请在 FirebaseMessagingService 类中为推送通知实现监听器。如果不实现这些功能,该服务将无法正常运行。
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)
}
}
}
实现 onNewToken
此外,还需实现 onNewToken 方法来处理令牌更新。这样可确保 Android 版无头移动 SDK 收到最新的推送通知令牌:
class MyFirebaseMessagingService : FirebaseMessagingService() {
// ...
override fun onNewToken(token: String) {
// Fetch the updated token from Firebase and update it in CCAI
CCAI.pushNotificationService?.updatePushToken(token)
}
}
在 AndroidManifest.xml 中注册该服务
将 Firebase Messaging 服务添加到您的 AndroidManifest.xml,以便系统可以将推送消息传递给您的服务:
<application>
<service
android:name=".firebase.MyFirebaseMessagingService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
初始令牌注册
在应用启动时(SDK 初始化后),主动注册当前的 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)
}
}
通知权限处理(Android 13 及更高版本)
在 Android 13(API 级别 33)及更高版本中,上述应用必须请求 POST_NOTIFICATIONS 运行时权限。SDK 为此提供了一项内置实用程序:
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")
}
在注册 FCM 令牌之前,在应用生命周期的早期(例如,在初始配置或首次启动期间)调用此方法,以便能够传送推送通知。