Android 專用的無標題行動 SDK:開始使用

本文說明如何在 Android 應用程式中整合及自訂 SDK。

開始使用

Android 適用的無頭行動 SDK 可讓您將 CCAI 平台的客服中心功能整合到內建的 Android UI 中。

您不必顯示 CCAI 平台品牌的 Widget,而是:

  • 將 CCAI Android SDK 模組新增為依附元件。

  • 以 Kotlin (建議) 或 Java 建構自己的畫面、流程和視覺設計。

  • 使用 SDK 執行下列操作:

    • 開始及管理即時通訊和語音工作階段。

    • 提供電子郵件、語音通話和轉移選項。

    • 支援智慧動作、附件和會後流程 (客戶滿意度調查、問卷調查、虛擬服務專員)。

CCAI 平台會處理客服中心邏輯 (路徑、佇列、管道、設定、報表)。您擁有完整的應用程式體驗 (使用者介面、流程和品牌)。

如要使用可設定主題的預先建構 UI,請改用標準行動版 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 平台執行個體需求條件

您需要存取 CCAI 平台執行個體的「開發人員設定」,才能取得下列資訊:

  • 公司金鑰

  • 公司密碼

  • 主機網址:CCAI 平台的主機名稱 (例如 your_subdomain.ccaiplatform.com)

這些值可用於:

  • 公司金鑰和主機網址:在 Android 應用程式中初始化 SDK。

  • 公司密碼:在後端簽署 JSON Web Token (JWT),用於驗證使用者。

網路和權限

您的應用程式必須允許輸出流量前往 CCAI 平台端點,以及您設定的任何語音供應商端點。

常見的 Android 權限包括 (實際清單可能因 SDK 版本和功能集而異):

  • 網際網路 / 網路狀態:用於所有 SDK 通訊。

  • 麥克風:用於語音通話。

  • 通知:適用於 Firebase 雲端通訊 (FCM) 推播通知。

  • 儲存空間 / 媒體:用於附件。

  • 相機:在智慧動作中拍攝相片或影片。

  • 螢幕畫面擷取:用於分享螢幕畫面 (MediaProjection)。

請按照 Android 作業系統指南宣告及要求執行階段權限。

推播通知

Headless Android SDK 會使用 FCM 傳送下列內容:

  • 來電通知。

  • 特定智慧動作和通話相關訊息。

  • 更新:協助在應用程式背景執行時維持狀態。

你需要:

  • Firebase 專案。

  • 應用程式模組中有效的 google-services.json。

  • 在應用程式中處理及註冊 FCM 權杖。

  • 應用程式中的自訂通知和通話使用者介面。

無頭 Android SDK 如何整合至應用程式

Android 適用的無頭行動 SDK 可視為三層:

CCAI 平台和 SDK (由 CCAI 平台處理)

SDK 會與 CCAI Platform 平台安全地互動,並提供下列功能:

  • 使用 JSON Web Token (JWT) 進行驗證。

  • 佇列和管道路徑中繼資料 (即時通訊、語音通話、電子郵件、外部轉向連結)。

  • 使用服務物件 (chatService、queueMenuService 等) 管理即時工作階段狀態。

  • 智慧動作、檔案附件和螢幕分享的安全傳輸管道。

  • 轉移邏輯和工作階段後階層評估。

Android 應用程式 (UI 和邏輯 - 由您處理)

你可以全面掌控視覺和導覽體驗:

  • 進入點:例如「說明」分頁或「與我們聯絡」按鈕。

  • 選單:顯示佇列的方式 (例如「帳單」、「技術支援」)。

  • 通話期間的使用者介面:自訂訊息泡泡、通話畫面和控制項。

  • 應用程式的用途:呼叫 SDK 服務 API 來啟動及結束工作階段、使用 Kotlin Coroutines 和 Flow 觀察 SDK 事件,以及驅動元件導覽。

CCAI 平台管理員入口網站設定

CCAI Platform 管理員會設定參與規則 (營業時間、可用管道、等待時間門檻和問卷調查)。SDK 會讀取這項設定,並以原始資料和事件的形式向應用程式公開。您決定如何在畫面上繪製該設定。

擷取公司憑證

整合 SDK 前,請先從 CCAI Platform 執行個體取得憑證:

  1. 使用管理員帳戶登入 CCAI 平台管理員入口。

  2. 依序前往「設定」>「開發人員設定」。

  3. 在「公司金鑰和密碼」下方,複製:

    • 公司金鑰

    • 公司密碼

  4. 記下 Host URL,也就是 CCAI 平台的主機名稱 (例如 your_subdomain.ccaiplatform.com)。

您將使用:

  • 在 Android 應用程式中:公司金鑰和主機網址。

  • 在後端伺服器中:公司密碼,用於簽署 JWT,以驗證使用者身分,以及 CCAI Platform 使用的選用自訂資料和環境。

將 SDK 新增至 Android 應用程式

Headless SDK 採用模組化架構,您會連同應用程式所需的特定功能模組 (例如 CCAIChat 或 CCAIScreenShare),一併安裝核心 CCAIKit。

新增 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 單例模式物件,在自訂應用程式類別中初始化 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 適用的無頭行動裝置 SDK 會使用 JSON Web Token (JWT) 驗證使用者,並安全地將情境資訊傳遞至服務專員的 CRM。

運作方式

SDK 採用簡化的兩步驟非同步驗證流程:

  1. SDK 判斷需要驗證使用者。

  2. 它會呼叫您的 CCAIDelegate 方法 - ccaiShouldAuthenticate() - 這是暫停函式。

  3. 應用程式會使用 `Company

  4. 應用程式會使用 Company Secret Code,在後端伺服器上遠端簽署 JWT。

  5. 接著,應用程式會將簽署的 JWT 傳遞至 CCAI.authService?.authenticate(jwt),換取驗證權杖。

  6. 系統會將驗證權杖傳回 SDK,完成連線。

實作 CCAIDelegate 進行驗證

應用程式必須實作 CCAIDelegate 介面。SDK 需要驗證時,會呼叫第一個暫停方法。

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

如要將情境資料傳遞給代理程式 (例如使用者的目前裝置 OS、位置或帳戶層級),後端必須先將 custom_data 物件插入 JWT 酬載,再簽署該酬載。

每筆自訂資料都必須格式化為 JSON 物件,內含標籤 (代理程式看到的內容)、值和類型。

支援的資料類型

  • string:標準文字 (例如「Pixel 8 Pro」)。

  • number:整數或浮點數 (例如 1234 或 99.99)。

  • date:13 位數的世界標準時間 Unix 時間戳記,包括毫秒 (例如 1537399655992)。

  • url:標準 HTTP/HTTPS 網址格式。

  • boolean:標準的 true 或 false 值。

服務專員可見度:您可以選擇將資料傳遞至 CCAI Platform 平台,這些資料會對真人服務專員隱藏,但可用於路徑或後端分析。如要這麼做,請在資料物件中加入 "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 設定

  1. 建立或使用現有的 Firebase 專案。

  2. 註冊 Android 應用程式,並下載 google-services.json 檔案。

  3. 將 google-services.json 放在應用程式模組目錄中。

  4. 在根層級 build.gradle.kts 中,新增 Google 服務外掛程式:

    // build.gradle.kts (Project)
    plugins {
        id("com.google.gms.google-services") version "4.4.2" apply false
    }
    
  5. 在應用程式層級的 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")
    }
    
  6. 同步處理專案。

向 SDK 註冊 FCM 權杖

透過 pushNotificationService 註冊 FCM 推送權杖,並將傳入的 FCM 資料酬載轉送至 SDK。應用程式必須負責顯示任何面向消費者的通知或通話中 UI。

導入 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 版 Headless Mobile 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 訊息服務新增至 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 權杖,這樣才能傳送推播通知。