本頁說明如何使用 Android SDK。
存取範例應用程式
如要下載 Android 範例應用程式,請按一下「Android example app」(Android 範例應用程式)。
如要使用 Android 行動 SDK 建立範例應用程式,您需要:
CCAI 平台入口網站公司金鑰和公司密鑰。
Android 5.0 (API 級別 21,Lollipop) 以上版本。
Firebase 雲端通訊或 Google Cloud 訊息,用於推播通知。
應用程式已遷移至 AndroidX。
Twilio SDK 升級規定
如果 Android SDK 是直接使用我們的套件整合,則 Twilio SDK 必須遵循特定版本,否則可以忽略。
// Twilio VoIP SDK
api 'com.twilio:voice-android:6.1.1'
// Twilio Conversations SDK
api 'com.twilio:conversations-android:3.1.0'
此外,Android SDK 已包含 Proguard 規則,可確保 Twilio Programmable Voice 程式庫不會遭到 ProGuard 移除,並可在 ProGuard 意外移除程式庫時用於疑難排解。
-keep class com.twilio.** { *; }
-keep class tvo.webrtc.** { *; }
-dontwarn tvo.webrtc.**
-keep class com.twilio.voice.** { *; }
-keepattributes InnerClasses
為支援最新 Twilio 版本,自 Android SDK 0.34.0 版起,SDK 不再與指定 Java 7 的應用程式二進位相容。如要使用這個版本和日後推出的版本,開發人員必須將應用程式升級至指定 Java 8。請參閱下列程式碼範例:
android {
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
取得公司金鑰和公司密鑰
使用管理員憑證登入管理員入口網站。
依序前往「設定」>「開發人員設定」>「公司金鑰和密鑰」。
擷取公司金鑰和公司密鑰。
安裝
將 Android SDK 存放區新增至根專案的 Gradle 設定。
build.gradle (Project)
allprojects {
repositories {
google()
jcenter()
maven {
url "https://sdk.ujet.co/android/"
}
}
}
build.gradle (module: app)
dependencies {
// Replace x.y.z with latest version of CCAI Platform SDK
def ujetSdkVersion = "x.y.z"
implementation "co.ujet.android:ujet-android:$ujetSdkVersion"
// CCAI Platform supports co-browse for Web SDK version 0.46.0 or
// higher.
// To use co-browse, declare the following dependency.
implementation "co.ujet.android:cobrowse:$ujetVersion"
}
調整公司設定
在 AndroidManifest.xml 檔案中,以中繼資料的形式輸入公司設定。
AndroidManifest.xml
<application>
// ...
<!-- Company Settings -->
<meta-data android:name="co.ujet.android.subdomain" android:value="@string/ujet_subdomain"/>
<meta-data android:name="co.ujet.android.companyKey" android:value="@string/ujet_company_key"/>
<meta-data android:name="co.ujet.android.companyName" android:value="@string/ujet_company_name"/>
// ...
</application>
strings.xml
<resources>
<string name="ujet_subdomain">YOUR_SUBDOMAIN</string>
<string name="ujet_company_key">YOUR_COMPANY_KEY</string>
<string name="ujet_company_name">YOUR_COMPANY_NAME</string>
</resources>
JWT 簽署
基於安全考量,使用者資訊必須在伺服器中簽署為 JWT。
範例應用程式含有用於測試的 APIManager,您必須將 UJET_COMPANY_SECRET 放入 mock/APIManager.java。APIManager 必須實作方法,啟動非同步呼叫來簽署 JWT 驗證權杖,並傳回權杖。
在實際工作環境中,您必須在伺服器上實作簽署程序。
public class APIManager {
public static final String UJET_COMPANY_SECRET = "Please input your UJET_COMPANY_SECRET from Ujet developer admin page";
// ...
}
初始化 SDK
在 Android 應用程式類別 onCreate 方法中初始化 SDK。
public class ExampleApplication extends Application implements UjetRequestListener {
@Override
public void onCreate() {
super.onCreate();
Ujet.init(this);
}
// ...
}
使用者驗證
使用者是指透過應用程式與客戶服務團隊聯絡的消費者。
為了在應用程式中驗證使用者,我們導入了 JWT 簽署機制。
Android SDK 需要驗證時,會要求簽署酬載。如果簽署成功,應用程式會將已簽署的 JWT 換成使用者的驗證權杖。
在 ExampleApplication 中,您應實作 UjetRequestListener 介面,用於簽署驗證權杖和自訂資料。
public class ExampleApplication extends Application implements UjetRequestListener {
@Override
public void onCreate() {
super.onCreate();
Ujet.init(this);
}
@Override
public void onSignPayloadRequest(Map<String, Object> payload, UjetPayloadType ujetPayloadType, UjetTokenCallback tokenCallback) {
if (ujetPayloadType == UjetPayloadType.AuthToken) {
// In production, you should implement this on your server.
// The server must implement a method that initiates an asynchronous call
to sign and return a JWT auth token.
APIManager.getHttpManager()
.getAuthToken(payload, UjetPayloadType.AuthToken, new UjetTokenCallback() {
@Override
public void onSuccess(@Nullable final String authToken) {
tokenCallback.onToken(authToken);
}
@Override
public void onFailure(@Nullable final String authToken) {
tokenCallback.onError();
}
});
}
}
}
詳情請參閱使用者驗證。
設定推播通知
本節將說明如何啟用行動推播通知。
準備 Firebase
請準備 Firebase 專案。
如果您已有專案,可以使用自己的專案,並略過這項程序。
在 Firebase 主控台中建立 Firebase 專案。
在 Firebase 控制台中,依序前往「設定」>「一般」,下載 google-services.json。

- 在 Firebase 控制台依序前往「設定」>「雲端通訊」,取得伺服器金鑰。

新增服務帳戶金鑰
您必須在行動應用程式中新增服務帳戶金鑰,才能接收推播通知。如要取得服務帳戶金鑰,請參閱「使用服務帳戶進行驗證」。
如要將服務帳戶金鑰新增至行動應用程式,請按照下列步驟操作:
在 CCAI Platform 入口網站中,依序點選「Settings」(設定) >「Developer Settings」(開發人員設定)。如果找不到「設定」選單,請按一下「選單」圖示 。
前往「Mobile Apps」(行動應用程式) 窗格。
按一下應用程式旁的 「Edit」(編輯)。系統會顯示「Edit Mobile App」(編輯行動應用程式) 對話方塊。
在「Service Account Field」(服務帳戶欄位) 中輸入服務帳戶金鑰,然後按一下「Save」(儲存)。
Android 用戶端設定
將
google-services.json複製到應用程式目錄,例如PROJECT_ROOT/app/google-services.json。使用下列程式碼取得
FCM權杖:FirebaseMessaging.getInstance().getToken() .addOnCompleteListener(task -> { if (!task.isSuccessful() || task.getResult() == null) { Log.w("FCM", "Couldn't get FCM token"); return; } String token = task.getResult(); Log.i("FCM", "FCM token: " + token); });系統會呼叫
FirebaseMessagingService,如果權杖重新整理,則會在資訊清單中註冊。詳情請參閱「在 Android 上設定 Firebase 雲端通訊用戶端應用程式」。public class YourFirebaseMessagingService extends FirebaseMessagingService { /** * There are two scenarios when onNewToken is called: * 1) When a new token is generated on initial app startup * 2) Whenever an existing token is changed * Under #2, there are three scenarios when the existing token is changed: * A) App is restored to a new device * B) User uninstalls/re-installs the app * C) User clears app data */ @Override public void onNewToken(String token) { Log.i("FCM", "FCM token updated: " + token); } }在應用程式類別中實作
UjetRequestListener.onRequestPushToken。UjetRequestListener.onRequestPushToken應傳回FCM/GCM權杖。public class YourApplication extends Application implements UjetRequestListener { /** * Return your FCM/GCM token */ @Override public String onRequestPushToken() { return yourToken(); // As shown in the previous step, you can get your token using FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> { }) } }處理推播通知。如要讓 Contact Center AI 平台 (CCAI Platform) 自行處理推播訊息,可以直接將資料傳遞至
UjetPushHandler.handle()。應用程式只會處理已設定
ujet_noti_type(或noti_type,用於回溯相容性) 欄位的訊息。否則,您可以選擇只將含有
ujet_noti_type的訊息傳送至UjetPushHandler.handle()進行處理。
以下是推播通知訊息範例:
{ "call_id" : 12345, "ujet_noti_type" : "connect_call", "noti_type" : "connect_call", "call_type" : "ScheduledCall", "fail_reason" : "none", "fail_details" : "none" }
處理 FCM 訊息
public class YourFirebaseMessagingService extends FirebaseMessagingService {
private UjetPushHandler ujetPushHandler;
@Override
public void onCreate() {
super.onCreate();
this.ujetPushHandler = new UjetPushHandler(this);
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (ujetPushHandler.handle(remoteMessage)) {
// Handled by CCAI Platform
} else {
// Handle your push notification message in here
}
}
}
處理 GCM 訊息
public class YourGcmListenerService extends GcmListenerService {
private UjetPushHandler ujetPushHandler;
@Override
public void onCreate() {
super.onCreate();
this.ujetPushHandler = new UjetPushHandler(this);
}
@Override
public void onMessageReceived(String s, Bundle bundle) {
if (ujetPushHandler.handle(bundle)) {
// Handled by CCAI Platform
} else {
// Handle your message
}
}
}
在 GcmReceiver 中處理 GCM 訊息 (舊方法)
public class YourGcmReceiver extends WakefulBroadcastReceiver {
private UjetPushHandler ujetPushHandler;
@Override
public void onReceive(Context context, Intent intent) {
ujetPushHandler = new UjetPushHandler(context);
if (ujetPushHandler.handle(intent.getExtras())) {
// Handled by CCAI Platform
} else {
// Handle your message
}
}
}
啟動應用程式
在要啟動應用程式的位置加入下列程式碼 (不含任何參數):
Ujet.start(new UjetStartOptions.Builder().build());
您也可以啟動 Android SDK,而不顯示啟動畫面。
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
.setSkipSplashEnabled(true)
.build();
Ujet.start(ujetStartOptions);
您也可以使用直接存取點,透過這個鍵從選單中的特定位置啟動 Android SDK:
String menuKey = "MENU_KEY";
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
.setMenuKey(menuKey)
.build();
Ujet.start(ujetStartOptions);
menuKey 可在 CCAI 平台入口網站中,透過直接存取點建立 (須具備管理員角色)。
依序前往「設定」>「待播清單」。
從選單結構中選取任何佇列。
勾選「建立直接存取點」。
在文字表單中輸入金鑰。
按一下 [儲存]。

您也可以使用特定票證 ID 啟動 Android SDK,將其傳遞至 CRM。即時通訊或通話連線後,系統會開啟這個票證 ID。
String ticketId = "TICKET_ID";
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
.setTicketId(ticketId)
.build();
Ujet.start(ujetStartOptions);
SDK 設定
啟動 Android SDK 前,您可以設定多個選項。請參閱 UjetOption 類別。只有在 CCAI 平台入口網站中,依序前往「Settings」>「Developer Settings」>「MMA」>「Edit」,並開啟「Enable PSTN Fallback」切換鈕,下表所述的「Fallback Phone Number」和「Network Sensitivity」選項才會生效。如果關閉「Enable PSTN Fallback」(啟用 PSTN 備用) 切換鈕,系統就不會改用 PSTN。CCAI 平台會使用預設網路敏感度 (0.85) 檢查網路連線。
| 選項 | 說明 | 值 | 預設值 |
|---|---|---|---|
| 記錄檔層級 | 要在 Logcat 中輸出的記錄層級。 | 整數。Android 記錄的記錄層級也是如此。最高速 | 5 (Log.Warn) |
| 預設語言 | 預設語言代碼。 | 字串。ISO 639 語言代碼。(例如 en 代表英文) | null |
| 備用電話號碼 | 如果無法連上網際網路,或管理員入口網站中沒有公司的代表電話號碼,系統會使用這個電話號碼做為備用號碼。 | 字串。電話號碼。 | null |
| 已啟用未偵測到的例外狀況處理常式 | 啟用未偵測到的例外狀況處理常式。如果 true,應用程式會在執行階段使用 Thread.setDefaultUncaughtExceptionHandler 處理所有未擷取的 SDK 例外狀況。不過,如果發生兩次相同的例外狀況,應用程式就會異常終止。 |
布林值。 | true |
| 網路敏感度 | 檢查網路狀態的靈敏度。 | 介於 0 和 1 之間的雙精度浮點數,其中 0 最不敏感,1 最敏感。如果值為 1,系統一律會改用 PSTN 通話。如要使用,建議先從 .97 開始。在入口網站中,依序前往「設定」>「開發人員設定」>「行動應用程式」>「備用」,即可查看覆寫這個值的電話號碼門檻。 |
0.85 |
| 已啟用深色模式 | 啟用深色模式主題。如果為 true,SDK 會在使用者開啟深色模式時套用深色模式主題,否則會忽略該動作。 |
布林值。 | false |
| 已啟用單一管道 | 設定選項,可顯示或略過單一頻道的頻道選取畫面。true:SDK 會顯示單一頻道選取畫面,而不是自動選取頻道,即使選單佇列中只有一個頻道啟用也一樣。 |
布林值。 | false |
| 自動縮小通話畫面 | 設定選項,預設自動最小化初始通話畫面 UI,或等待使用者最小化。 | 布林值。 | false |
| 啟用代理圖示邊框 | 設定選項,用於顯示或移除代理圖示周圍的圓形框線。 | 布林值。 | false |
| 挑選器檢視畫面中的靜態字型大小 | 設定選項,可自動調整或停用挑選器項目文字大小。 | 布林值。 | false |
| 隱藏 Chat 中的媒體附件 | 設定選項,用於在即時通訊使用者介面中顯示或隱藏媒體附件圖示。 | 布林值。 | false |
忽略「READ_PHONE_STATE」權限 |
如果設為 true,SDK 就不會要求 READ_PHONE_STATE 權限。如果不想使用應用程式內 IVR 通話,請將這個旗標設為 true,避免要求這項權限,而且應用程式必須明確移除 CCAI Platform SDK 的 android.permission.READ_PHONE_STATE 權限。請注意,我們不建議將這項權限設為 true,因為應用程式內 IVR 通話必須取得這項權限才能運作。 |
布林值 | false |
| Cobrowse.io 授權金鑰 (如適用) | 設定 Cobrowse.io 程式庫的設定選項。如要查看 Cobrowse 授權金鑰,請登入 https://cobrowse.io/dashboard/settings,然後前往「License Key」部分。 |
字串 | null |
| 自訂即時通訊標頭標題 | 設定選項,可在即時通訊 UI 中自訂即時通訊標題文字。 | 字串 | null |
| 自訂即時通訊 UI 快速回覆 | 設定選項,在對話 UI 中自訂虛擬服務專員的快速回覆。虛擬服務專員快速回覆預設會分組顯示,但如果您想個別顯示,可以使用這個設定選項,將 QuickReplyButtonsStyle 設為 INDIVIDUAL | UjetStylesOptions | QuickReplyButtonsStyle.GROUPED |
| 自訂即時通訊 UI 的各種屬性 | 設定選項,可自訂字型、背景顏色、圖示等各種屬性。 | UjetStylesOptions | null |
| 隱藏狀態列 | 用於顯示或隱藏狀態列的設定選項。如果值為 true,SDK 會隱藏狀態列。 | 布林值 | false |
| 設定載入中旋轉圖示可繪製資源 | 設定選項,用於自訂整個應用程式的載入旋轉圖示檢視畫面。如果無法使用或為空值,則會使用預設的載入檢視畫面。 | 整數 | null |
| 已停用橫向顯示比例 | 停用橫向模式。如果值為 true,則不會套用橫向顯示比例。 | 布林值 | false |
| 隱藏聊天室中的「發起新對話」內嵌按鈕 | 設定選項,用於在即時通訊 UI 中顯示或隱藏「發起新對話」內嵌按鈕。 | 布林值 | false |
| 顯示 CSAT 略過按鈕 | 設定選項,用於顯示或隱藏 CSAT 對話方塊中的略過按鈕 | 布林值 | false |
| 禁止使用者終止即時通訊 | 設定選項,用於在即時通訊使用者介面中顯示或隱藏結束即時通訊按鈕 | 布林值 | false |
| 隱藏下載即時通訊轉錄稿 | 在即時通訊動作選單和即時通訊使用者介面中,顯示或隱藏「下載即時通訊轉錄稿」按鈕。如果您在 ujet_common_hide 字串中加入空格,Hide 文字就會消失,只會顯示返回箭頭。 |
整數。值:
|
0
|
| 關閉全域層級的推播通知 | 如果將 UjetOption.setPushNotificationsAllowed 設為 false,系統會略過所有推播通知依附元件,並防止推播通知傳送給使用者。 |
布林值 | true |
| 隱藏「下一個可預訂的日期」 | 在非營業時間的即時通訊報到畫面上,顯示或隱藏「下次可提供服務的時間」訊息。 | 布林值 | false |
| 隱藏「重新開始」 | 在非營業時間的即時通訊報到畫面,顯示或隱藏「重新開始」按鈕。 | 布林值 | false |
UjetOption ujetOption = new UjetOption.Builder()
.setLogLevel(Log.INFO)
.setDefaultLanguage("en")
.setFallbackPhoneNumber("+18001112222")
.setUncaughtExceptionHandlerEnabled(false)
.setNetworkSensitivity(0)
.setDarkModeEnabled(true)
.setShowSingleChannelEnabled(true)
.setAutoMinimizeCallView(true)
.setShowAgentIconBorderEnabled(true)
.setStaticFontSizeInPickerView(true)
.setHideMediaAttachmentInChat(true)
.setIgnoreReadPhoneStatePermission(true)
.setCobrowseLicenseKey("COBROWSE_IO_LICENSE_KEY_HERE")
.setCobrowseURL("COBROWSE_IO_API_URL_HERE")
.setCustomChatHeaderTitle("CHAT_HEADER_TITLE_TEXT")
.setUjetStylesOptions(
new UjetStylesOptions.Builder()
.setChatQuickReplyButtonsStyle(QuickReplyButtonsStyle.INDIVIDUAL)
.setChatStyles(new ChatStyles(...)) // See `Content Cards Theme` item
.build() )
.setBlockChatTerminationByEndUser(true)
.setHideStatusBar(true)
.setLoadingSpinnerDrawableRes(R.drawable.RESOURCE_NAME)
.setLandscapeOrientationDisabled(true)
.setShowCsatSkipButton(false)
.setHideDownloadChatTranscript(0) // 0 to 3. 0 = Show everywhere, 1 = Hide from the options menu, 2 = Hide from the post chat screen, 3 = Hide from both the options menu and the post chat screen.
.setPushNotificationsAllowed(true)
.setHideNextAvailability(true)
.setHideStartOver(true)
.build();
//The following customizes various attributes in chat UI
ChatStyles chatStyles = new ChatStyles();
chatStyles.setBackButton(new BackButtonStyle(false, "ujet_agent_sample")); //customizes back button styles
chatStyles.setHeader(...); //customizes chat header styles
chatStyles.setAgentMessageBubbles(...); //customizes agent messages styles
chatStyles.setConsumerMessageBubbles(...); //customizes consumer messages styles
chatStyles.setSystemMessages(...); //customizes system messages styles
chatStyles.setEndChatButton(...); //customizes end chat button styles
chatStyles.setTimeStamps(...); //customizes timestamp styles
chatStyles.setUserInputBar(...); //customizes user input bar styles
UjetOption ujetOption = new UjetOption.Builder()
.setUjetStylesOptions(
new UjetStylesOptions.Builder()
.setChatStyles(chatStyles)
.build()
)
//The following customizes various attributes in chat UI using json file. Store json file in assets folder
//and create a method to read json file contents and convert it into json string.
String chatStylesFromJson = parseJsonContentsFromAssetsFolder();
UjetOption ujetOption = new UjetOption.Builder()
.setUjetStylesOptions(
new UjetStylesOptions.Builder()
.setChatStyles(chatStylesFromJson)
.build()
)
應用程式權限
應用程式需要下列權限,並會在必要時要求使用者授予這些權限。
| 權限 | 說明 |
|---|---|
| CAMERA | 用於智慧動作,可拍照及錄影 |
| 麥克風 | 允許應用程式透過 Twilio 進行 VoIP 通話 |
| 儲存空間 | 允許應用程式儲存相片和影片 |
語言偏好設定
Android SDK 會按照下列優先順序決定語言。
在應用程式啟動畫面中選取的語言。
使用
UjetOptions選取的預設語言。您可以在UjetOptions中使用setDefaultLanguage("en")設定預設語言。詳情請參閱 SDK 設定一節中的「預設語言」。如果應用程式支援,系統會使用在裝置中選取的裝置語言 (依序前往「設定」>「一般」>「語言」)。
如果應用程式不支援裝置語言,但支援最接近的母方言,則會使用最接近裝置語言的方言。舉例來說,如果使用者在裝置中選取古巴西班牙文做為語言,而應用程式不支援古巴西班牙文,但支援上層方言西班牙文,則系統會使用西班牙文。
如果應用程式不支援裝置語言,則會預設使用英文。
偏好的管道
「偏好管道」參數可讓您將消費者直接導向特定管道。使用者會略過管道選取步驟,直接透過 Preferred Channel 參數中指定的管道發起聯絡。
UjetStartOptions.preferredChannel
Ujet.start(new)
UjetStartOptions.Builder().setPreferredChannel
(UjetPreferredChannel.UjetPreferredChannelChat).build());
事件通知
您可以視需要設定 UjetEventListener,接收應用程式事件通知。
可用的事件類型和說明如下。
Ujet.setUjetEventListener(new UjetEventListener() {
@Override
public void onEvent(UjetEventType eventType, HashMap<String, Object> eventData) {
// eventType specifies the event type and eventData holds the data related to the event.
// You can parse the eventData and here we are just logging the event type and event data.
Log.i("CCAI Platform Event Type", eventType.getValue());
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, Object> entry : eventData.entrySet()) {
builder.append(entry.getKey()).append(" : ").append(entry.getValue()).append("\n");
}
Log.i("CCAI Platform Event Data", builder.toString());
}
});
| 事件類型 | 說明 | 事件包含的資料 |
|---|---|---|
EmailClicked |
使用者點選電子郵件管道時觸發。 | 佇列選單資料 |
EmailSubmitted |
在使用者傳送電子郵件時觸發。 | 佇列選單資料、電子郵件提交資料 |
SessionPaused |
使用者縮小即時通訊或通話工作階段時觸發。 | 工作階段資料 |
SessionResumed |
當使用者從背景切換回即時通訊或通話工作階段時,就會觸發。 | 工作階段資料 |
SessionCreated |
建立即時通訊或通話工作階段時觸發。 | 佇列選單資料、工作階段建立資料 |
SessionEnded |
在即時通訊或通話工作階段結束時觸發。 | 佇列選單資料、工作階段建立資料、工作階段結束資料 |
SdkTerminated |
SDK 關閉時 (包括意外關閉) 觸發。 | SDK 終止資料 |
ContentCardClicked |
使用者點選內容資訊卡時觸發。 | 內容資訊卡點擊資料 |
ContentCardButtonClicked |
點選內容資訊卡按鈕時觸發。 | 內容資訊卡按鈕點擊資料 |
QuickReplyClicked |
使用者點選快速回覆時觸發。 | 快速回覆點擊資料 |
MessageLinkClicked |
在使用者點選連結時觸發。 | 郵件連結點擊資料 |
佇列選單資料
| 鍵 | 類型 | 說明 |
|---|---|---|
event_name |
字串 | 包含事件名稱。例如「已點擊電子郵件」。 |
application |
字串 | 包含應用程式名稱。例如「Android」。 |
app_id |
字串 | 包含與 Context.getPackageName() 相同的應用程式 ID。 |
app_version |
字串 | 包含應用程式版本名稱和版本代碼。例如「0.32.0 (123)」。 |
sdk_version |
字串 | 包含 SDK 版本。例如「0.32.0」。 |
timestamp |
字串 | 包含世界標準時間的時間戳記 (格式為 yyyy-MM-dd'T'HH:mm:ss'Z')。 |
device_model |
字串 | 包含使用者裝置型號。例如「Google Pixel」。 |
device_version |
字串 | 包含使用者裝置版本。例如「10, Q, SDK 29」。 |
company |
字串 | 內含公司名稱。例如「公司」。 |
menu_name |
字串 | 包含葉節點的名稱 (使用者最後選取的選單項目)。例如「子選單」。 |
menu_id |
字串 | 包含葉節點 (使用者最後選取的選單) 的 ID。例如「123」。 |
menu_path |
字串 | 包含使用者選取的完整選單序列。例如「上層 / 下層 / 子選單」。 |
menu_key |
字串 | 包含 DAP 金鑰,為選用項目。例如「special_user_menu」。 |
電子郵件提交資料
| 鍵 | 類型 | 說明 |
|---|---|---|
has_attachments |
布林值 | 如果電子郵件有任何附件,則傳回 True,否則傳回 False。 |
工作階段資料
| 鍵 | 類型 | 說明 |
|---|---|---|
event_name |
字串 | 包含事件名稱。例如「已點擊電子郵件」。 |
type |
字串 | 包含工作階段類型。例如「即時通訊」或「通話」。 |
timestamp |
字串 | 包含世界標準時間的時間戳記 (格式為 yyyy-MM-dd'T'HH:mm:ss'Z')。 |
工作階段建立日期
| 鍵 | 類型 | 說明 |
|---|---|---|
session_id |
字串 | 包含工作階段 ID。例如「100」。 |
type |
字串 | 包含工作階段類型。例如「即時通訊」或「通話」。 |
end_user_identifier |
字串 | 包含使用者 ID。例如「John」。 |
messages_end_user |
字串 | 包含使用者訊息數量,且僅適用於即時通訊工作階段。例如「3」。 |
messages_agent |
字串 | 包含服務專員訊息數量,且僅適用於即時通訊工作階段。例如「3」。 |
工作階段結束資料
| 鍵 | 類型 | 說明 |
|---|---|---|
agent_name |
字串 | 包含代理名稱。例如「John」。 |
ended_by |
字串 | 包含結束工作階段者的詳細資料。可能的值包括「agent」(代理結束工作階段)、「end_user」(使用者結束工作階段)、「timeout」(即時通訊逾時) 或「dismissed」(即時通訊已關閉)。 |
duration |
字串 | 包含工作階段持續時間 (以秒為單位),且僅適用於通話工作階段。例如「30 秒」。 |
SDK 終止資料
| 鍵 | 類型 | 說明 |
|---|---|---|
event_name |
字串 | 包含事件名稱。例如「已點擊電子郵件」。 |
內容資訊卡點擊資料
| 鍵 | 類型 | 說明 |
|---|---|---|
title |
字串 | 資訊卡標題。 |
title |
字串 | 資訊卡標題。 |
subtitle |
字串 | 資訊卡副標題。 |
body |
字串 | 內容資訊卡的說明。 |
link | 字串 | 網頁連結或深層連結。SDK 會使用 OS 功能開啟。 |
event_params | dictionary | 包含點擊事件額外資訊的字典。SDK 會使用這個。 |
內容資訊卡按鈕點擊資料
| 鍵 | 類型 | 說明 |
|---|---|---|
title |
字串 | 資訊卡標題。 |
title |
字串 | 資訊卡標題。 |
link | 字串 | 網頁連結或深層連結。SDK 會使用 OS 功能開啟。 |
event_params | dictionary | 包含點擊事件額外資訊的字典。SDK 會使用這個。 |
快速回覆點擊資料
| 鍵 | 類型 | 說明 |
|---|---|---|
title |
字串 | 資訊卡標題。 |
title |
字串 | 資訊卡標題。 |
link | 字串 | 網頁連結或深層連結。SDK 會使用 OS 功能開啟。 |
event_params | dictionary | 包含點擊事件額外資訊的字典。SDK 會使用這個。 |
郵件連結點擊資料
| 鍵 | 類型 | 說明 |
|---|---|---|
event_name |
字串 | 包含事件名稱,例如「Message Link Clicked」。 |
link |
字串 | 網頁連結或深層連結。SDK 會使用 OS 功能開啟。 |
將自訂資料傳送至客戶關係管理系統
自訂資料可傳送給客服專員,並顯示在來電/即時通訊的支援單中。
傳送自訂資料的方法有兩種:
簽署方法:使用 JWT 預先定義資料簽署。
未簽署方法:使用純 JSON 的預先定義資料 (不建議)。
使用已簽署的方法傳送自訂資料
如要使用簽署方法傳送自訂資料,請導入簽署方法。
首先,將自訂資料擷取至主機應用程式,然後傳送至伺服器進行簽署。在伺服器上,您可以使用定義的表單新增其他資料。使用公司密鑰簽署,然後透過 JWT 傳回。
public class ExampleApplication extends Application implements UjetRequestListener {
@Override
public void onCreate() {
super.onCreate();
Ujet.init(this);
}
@Override
public void onSignPayloadRequest(Map<String, Object> payload, UjetPayloadType ujetPayloadType, UjetTokenCallback tokenCallback) {
// ...
if (ujetPayloadType == UjetPayloadType.CustomData) {
/**
* These codes are for providing signed custom data.
* Add some data from app, and add more sensitive data from server and sign it.
*/
UjetCustomData appCustomData = new UjetCustomData();
appCustomData.put("model", "Model", "MODEL1234");
appCustomData.put("customer_id", "Customer ID", 12345);
appCustomData.put("temperature", "Temperature", 70.5f);
appCustomData.put("purchase_date", "Purchase Date", new Date());
appCustomData.put("battery", "Battery", "52%");
appCustomData.put("location", "Location", "San Francisco, CA, United States");
appCustomData.putURL("dashboard_url", "Dashboard URL", "https://internal.dashboard.com/12345");
payload.put("custom_data", appCustomData.getData());
tokenCallback.onToken(APIManager.getHttpManager().getSignedCustomData(payload));
}
// ...
}
}
使用未簽署方法傳送自訂資料
Google 建議您使用簽署方法,在應用程式中傳送自訂資料。詳情請參閱「使用簽署方法傳送自訂資料」。
如要傳送未簽署的資料,請使用啟動選項啟動 Android SDK,並透過 UjetStartOptions.Builder#setUnsignedCustomData 設定自訂資料,而 UjetTokenCallback 應呼叫 onToken(null)。
HashMap<String, Object> jsonData = new HashMap<>();
// Convert json string into hashmap object and store it in jsonData
UjetCustomData customData = new UjetCustomData();
customData.putObject("external_chat_transfer", jsonData); // Use `external_chat_transfer` key to send chat transcript data
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
.setUnsignedCustomData(customData)
.build();
Ujet.start(ujetStartOptions);
使用未簽署的自訂資料傳送外部即時通訊轉錄稿
您可以在外部即時通訊開始時,使用未簽署的自訂資料,將轉錄稿傳送至 CCAI Platform。使用 UjetCustomData.putObject("external_chat_transfer", hashMapObject),以 JSON 格式設定轉錄稿資料,如下所示:
HashMap<String, Object> jsonData = new HashMap<>();
// Convert json string into hashmap object and store it in jsonData
UjetCustomData customData = new UjetCustomData();
customData.putObject("external_chat_transfer", jsonData); // Use `external_chat_transfer` key to send chat transcript data
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
.setUnsignedCustomData(customData)
.build();
Ujet.start(ujetStartOptions);
JSON 格式:
greeting_override:字串agent:字典name:字串avatar:字串 [服務專員顯示圖片的網址,選填]
transcript:陣列sender:字串 ["end_user" 或 "agent"]timestamp:字串 [例如「2021-03-15 12:00:00Z」]content:陣列type:字串 [text 或 media]text:字串 [文字類型必填]media:字典 [媒體類型必填]type:字串 [image 或 video]url:字串 [指向媒體檔案的公開網址]
JSON 範例:
{
"greeting_override": "Please hold while we connect you with a human agent.",
"agent": {
"name": "Name",
"avatar": "avatar url"
},
"transcript": [
{
"sender": "agent",
"timestamp": "2021-03-15 12:00:15Z",
"content": [
{
"type": "text",
"text": "**Suggestions shown:**\n\n* Help with batch or delivery\n* Help with metrics or order feedback\n* Help with Instant Cashout"
}
]
},
{
"sender": "end_user",
"timestamp": "2021-03-15 12:00:16Z",
"content": [
{
"type": "text",
"text": "Help with batch or delivery"
}
]
}
]
}
您可以在文字類型上使用 Markdown。支援的格式如下:
粗體
斜體
底線
換行
項目符號清單
編號清單
連結
自訂資料格式
本節說明可在 JWT 中傳遞的自訂資料格式。
JSON 編碼為 JWT
JSON 應包含 iat 和 exp,以便驗證 JWT。自訂資料的物件是 custom_data 鍵的值。
{
"iat" : 1537399656,
"exp" : 1537400256,
"custom_data" : {
"location" : {
"label" : "Location",
"value" : "1000 Stockton St, San Francisco, CA, United States",
"type" : "string"
},
"dashboard_url" : {
"label" : "Dashboard URL",
"value" : "http://(company_name)/dashboard/device_user_ID",
"type" : "url"
},
"contact_date" : {
"label" : "Contact Date",
"value" : 1537399655992,
"type" : "date"
},
"membership_number" : {
"label" : "Membership Number",
"value" : 62303,
"type" : "number"
},
"model" : {
"label" : "Model",
"value" : "iPhone",
"type" : "string"
},
"os_version" : {
"label" : "OS Version",
"value" : "12.0",
"type" : "string"
},
"last_transaction_id" : {
"label" : "Last Transaction ID",
"value" : "243324DE-01A1-4F71-BABC-3572B77AC487",
"type" : "string"
},
"battery" : {
"label" : "Battery",
"value" : "-100%",
"type" : "string"
},
"bluetooth" : {
"label" : "Bluetooth",
"value" : "Bluetooth not supported",
"type" : "string"
},
"wifi" : {
"label" : "Wi-Fi",
"value" : "Wi-Fi not connected",
"type" : "string"
},
"ssn" : {
"invisible_to_agent" : true,
"label" : "Social Security Number",
"value" : "102-186-1837",
"type" : "string"
}
}
}
鍵是資料的專屬 ID。類型是指值的類型。
string- JSON 字串
number- integer、float
date- 13 位數的 UTC Unix 時間戳記格式。(包含毫秒)
url- HTTP 網址格式
標籤是客戶關係管理頁面上的顯示名稱。
禁止顯示自訂資料
您可以搭配自訂資料物件使用 invisible_to_agent 屬性,防止已簽署或未簽署的自訂資料顯示在代理程式轉接器中。在上述範例中,由於 ssn 物件包含 "invisible_to_agent" : true,因此代理程式轉接器不會顯示使用者的身分證字號。
在自訂資料物件中加入 "invisible_to_agent" : true 屬性時,預期會發生下列行為:
- 自訂資料會包含在工作階段中繼資料檔案中。
- 自訂資料不會納入客戶關係管理記錄。
詳情請參閱「在代理程式轉接器中查看工作階段資料」。
保留資料屬性
工作階段開始時,您可以將保留的資料屬性,以已簽署自訂資料的形式傳送至 Contact Center AI Platform (CCAI Platform)。詳情請參閱「傳送預留資料屬性」。
以下是自訂資料中保留資料屬性的範例:
{
"custom_data": {
"reserved_verified_customer": {
"label": "Verified Customer",
"value": false,
"type": "boolean"
},
"reserved_bad_actor": {
"label": "Bad Actor",
"value": false,
"type": "boolean"
},
"reserved_repeat_customer": {
"label": "Repeat Customer",
"value": false,
"type": "boolean"
}
}
}
將每個值設為 true 或 false。
reserved_verified_customer:如果您認為這位使用者是合法客戶,請輸入true。reserved_bad_actor:如果您認為這位使用者可能是惡意人士,請使用true。reserved_repeat_customer:如果您判定這位使用者先前曾與客服中心聯絡,請設為true。
備用
您可以使用 UjetErrorListener 做為非預期錯誤的備用方案。如果未設定這個事件監聽器或傳回 false,Android SDK 會處理錯誤。
只有在「設定」>「開發人員設定」>「MMA」>「編輯」彈出式視窗中,將「啟用 PSTN 備用」切換鈕設為「開啟」時,Android SDK 才會將使用者重新導向至撥號程式,並提供備用號碼,否則會退出 SDK。
| 錯誤類型 | 錯誤代碼 | 觸發條件 |
|---|---|---|
| NETWORK_ERROR | 1 | 無法連上網路。請注意,如果是在即時通訊、通話或評分畫面中無法連上網路,系統不會觸發這項錯誤。 |
| AUTHENTICATION_ERROR | 100 | 驗證期間發生未預期的錯誤。 |
| AUTHENTICATION_JWT_ERROR | 101 | 驗證 JWT 時發生未預期的錯誤 (例如剖析錯誤)。 |
| VOIP_CONNECTION_ERROR | 1000 | 無法與 VoIP 供應商建立連線。這項作業會透過 VoIP SDK 的回呼處理。 |
| VOIP_LIBRARY_NOT_FOUND | 1001 | 系統預期會使用 VoIP 供應商連線通話,但找不到供應商。如果開發人員整合錯誤的 SDK,或未在依附元件中加入 VoIP 供應商程式庫,就可能發生這種情況。 |
| CHAT_LIBRARY_NOT_FOUND | 1100 | 找不到即時通訊程式庫時,會發生這個錯誤。如果開發人員整合錯誤的 SDK,或未在依附元件中加入 Twilio Chat 程式庫,就可能發生這種情況。 |
Ujet.setUjetEventListener(new UjetEventListener() {
@Override
public void onEvent(UjetEventType eventType, HashMap<String, Object> eventData) {
// eventType specifies the event type and eventData holds the data related to the event.
// You can parse the eventData and here we are just logging the event type and event data.
Log.i("CCAI Platform Event Type", eventType.getValue());
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, Object> entry : eventData.entrySet()) {
builder.append(entry.getKey()).append(" : ").append(entry.getValue()).append("\n");
}
Log.i("CCAI Platform Event Data", builder.toString());
}
});
深層連結
如要對 IVR (PSTN) 通話使用智慧動作,您必須在專案中設定深層連結。
深層連結格式是專屬 URI,例如:
ujet:// <package_name>/smartchannel.
此外,您必須在管理入口網站中設定這個連結,或任何會重新導向至這個連結的網址 (依序前往「設定」>「作業管理」>「啟用傳送簡訊下載應用程式」)。
您必須在資訊清單中新增包含深層連結的意圖篩選器。
<activity android:name="co.ujet.android.activity.UjetActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="<package_name>"
android:scheme="ujet"
android:path="/smartchannel" />
</intent-filter>
</activity>
聊天室復原能力
如要提高聊天室的正常運作時間,請設定聊天室復原能力。這會新增次要備用訊息媒體層,在主要媒體層失敗時使用。
如要新增這項功能,請在模組層級的 build.gradle 檔案中加入以下依附元件:
dependencies {
implementation "co.ujet.android:chat_blue:VERSION"
}
將 VERSION 替換為最新版 UJET SDK。
來電行為變更
從 Android 10 版本裝置開始,當主機應用程式在背景執行時,使用者不會直接收到來電。而是使用通知提醒使用者有來電 (即使手機處於鎖定狀態),讓他們選擇接聽或拒接。
當主機應用程式在背景執行,且在來電前鎖定螢幕時,系統會顯示相同的通知。這項行為變更是為了遵守 Google 最近對應用程式在背景執行時啟動活動的限制。如果主機應用程式在前景執行,或在搭載 Android 10 以下版本的裝置上執行,則行為不受影響。
自訂 SDK 工作階段
本節說明如何進一步自訂 SDK。
檢查現有工作階段
開始工作階段前,請使用所述方法檢查是否有任何現有或進行中的工作階段。如果存在,您可以提示使用者繼續或取消。
變更使用者時,這一點尤其重要。
if (Ujet.getStatus() != UjetStatus.None) {
// Display alert to cancel login or resume existing session
}
中斷工作階段連線
如要中斷任何進行中的工作階段,請參閱這個方法。
使用這個方法前,請務必透過 Ujet.getStatus() 檢查這類工作階段是否存在。如果想在 SDK 中斷工作階段連線後執行動作(例如顯示訊息或關閉應用程式),可以使用下一節介紹的回應回呼 onFinished(),否則請將回呼設為空值。
Ujet.disconnect(new UjetResponseCallback() {
@Override
public void onFinished() {
// `onFinished()` is triggered after CCAI Platform disconnects the session.
finish(); // Finishes the activity.
}
});
清除快取中的使用者資料
當使用者相關資料在應用程式中更新或變更時,您必須負責清除快取。舉例來說,如果使用者已登出,請叫用方法移除該使用者的快取,以便在下次啟動 SDK 時,為新使用者啟動新的工作階段。
Ujet.clearUserData();
隱藏 SDK
您可以使用 Ujet.hideSDK() 方法隱藏 SDK。舉例來說,如果 SDK 干擾應用程式使用者介面,這項功能就非常實用。請先使用 Ujet.init() 初始化 SDK,再呼叫這個方法。如果 SDK 成功隱藏,Ujet.init() 會傳回 true,否則會傳回 false。隱藏 SDK 後,您可以使用 Ujet.start() 方法重新啟動。
以下範例會隱藏 SDK:
Ujet.hideSDK();
設定外部轉移連結圖示
如要自訂外部轉移連結管道中的圖示,請將圖示上傳至應用程式的可繪項目資料夾,並確保在 CCAI Platform 入口網站中建立外部轉移連結時,使用相同的圖示名稱。請依序前往「設定」>「Chat」>「外部轉移連結」>「查看連結」>「新增轉移連結」。
如果 CCAI Platform 入口網站中的圖示名稱與上傳至應用程式的圖示不符,Android SDK 會使用預設圖示。
設定問卷調查「感謝」圖示
如要自訂或覆寫問卷調查感謝頁面中的圖示,請將圖示上傳至應用程式的可繪項目資料夾,並使用 ujet_survey_thank_you_icon 做為圖示名稱。
自訂 UI 和字串
本節說明如何自訂字串、內容資訊卡、主題和即時通訊標頭。
字串
您可以覆寫 strings.xml 中每個字串的鍵,自訂應用程式中使用的字串。
<resources>
<!--Greeting title and message in splash screen-->
<string name="ujet_greeting_title">Customer Support</string>
<string name="ujet_greeting_description">runs on UJET</string>
</resources>

自訂文字大小
如要自訂應用程式中使用的標題、說明和挑選器文字大小,請覆寫 dimens.xml 中的下列索引鍵。
可自訂文字大小的功能如下:
<resources>
<!-- Don't include the following tags if you don't want to customize any of these keys and prefer to use the CCAI Platform default values instead. -->
<!-- You can customize title text size by updating value here. -->
<dimen name="ujet_title">10sp</dimen>
<!-- You can customize description text size by updating value here. -->
<dimen name="ujet_description">10sp</dimen>
<!-- You can customize picker text size by updating value here. -->
<dimen name="ujet_picker_item_text_size">10sp</dimen>
</resources>

主題
請按照下列步驟自訂主題和背景。步驟 1 是主題,步驟 2 是背景。
覆寫 style.xml 中每個樣式項目的索引鍵,即可自訂主題。例如,假設使用者要求系統 將文字從英文翻譯成法文
<!--Default style applies to both Light and Dark Mode Themes--> <style name="Ujet"> <item name="ujet_typeFace">ProximaNova-Reg.otf</item> <item name="ujet_colorPrimary">@color/primaryDefault</item> <item name="ujet_colorPrimaryDark">@color/primaryDarkDefault</item> <item name="ujet_buttonRadius">10dp</item> <item name="ujet_companyLogo">@drawable/your_company_logo_default</item> <!-- You can customize the avatar in waiting UI before call or chat is connected by using the following option. --> <item name="ujet_defaultAvatar">@drawable/your_default_avatar</item> </style> <!--This is optional and can be used to update style in Light Mode Theme only--> <style name="Ujet.Light"> <item name="ujet_typeFace">ProximaNova-Reg.otf</item> <item name="ujet_colorPrimary">@color/primaryLightMode</item> <item name="ujet_colorPrimaryDark">@color/primaryDarkLightMode</item> <item name="ujet_buttonRadius">10dp</item> <item name="ujet_companyLogo">@drawable/your_company_logo_light_mode</item> <!-- You can customize the avatar in waiting UI before call or chat is connected by using the following option. --> <item name="ujet_defaultAvatar">@drawable/your_default_avatar</item> </style> <!--This is optional and can be used to update style in Dark Mode Theme only--> <style name="Ujet.Dark"> <item name="ujet_typeFace">ProximaNova-Reg.otf</item> <item name="ujet_colorPrimary">@color/primaryDarkMode</item> <item name="ujet_colorPrimaryDark">@color/primaryDarkForDarkMode</item> <item name="ujet_buttonRadius">10dp</item> <item name="ujet_companyLogo">@drawable/your_company_logo</item> <!-- You can customize the avatar in waiting UI before call or chat is connected by using the following option. --> <item name="ujet_defaultAvatar">@drawable/your_default_avatar</item> </style>您可以覆寫 style.xml 中每個樣式項目的索引鍵,自訂應用程式的背景顏色。螢幕截圖顯示可自訂的背景顏色。
<style name="Ujet"> <!-- Don't include the following tags if you don't want to customize any of these keys and prefer to use the CCAI Platform default values instead. --> <!-- You can customize light mode theme background color by updating value here in hex. --> <item name="ujet_colorBackground">@color/backgroundDefault</item> <!-- You can customize dark mode theme background color by updating value here in hex. --> <item name="ujet_colorBackgroundDark">@color/backgroundDefaultDark</item> </style>
自訂即時通訊標題
您可以在使用者介面中自訂即時通訊標題文字。
您可以使用下列選項自訂即時通訊標題文字:
<item name="ujet_chatCustomHeaderTextColor">@color/chatHeaderTextLightMode</item>
<item name="ujet_chatCustomHeaderTextColowDark">@color/chatHeaderTextDarkMode</item>
<item name="ujet_chatCustomHeaderTextSize">16sp</item>
<item name="ujet_chatCustomHeaderTextStyle">bold</item>
您可以使用下列選項,在即時通訊使用者介面中自訂虛擬服務專員快速回覆:
<item name="ujet_colorChatQuickReplyButtonBackground">@color/chatQuickReplyButtonBackgroundLightMode</item>
<item name="ujet_colorChatQuickReplyButtonBackgroundDark">@color/chatQuickReplyButtonBackgroundDarkMode</item>
<item name="ujet_colorChatQuickReplyButtonPressedBackground">@color/chatQuickReplyButtonPressedBackgroundLightMode</item>
<item name="ujet_colorChatQuickReplyButtonPressedBackgroundDark">@color/chatQuickReplyButtonPressedBackgroundDarkMode</item>
<item name="ujet_colorChatQuickReplyButtonText">@color/chatQuickReplyButtonTextLightMode</item>
<item name="ujet_colorChatQuickReplyButtonTextDark">@color/chatQuickReplyButtonTextDarkMode</item>
<item name="ujet_colorChatQuickReplyButtonPressedText">@color/chatQuickReplyButtonPressedTextLightMode</item>
<item name="ujet_colorChatQuickReplyButtonPressedTextDark">@color/chatQuickReplyButtonPressedTextDarkMode</item>
<item name="ujet_colorChatQuickReplyButtonStroke">@color/chatQuickReplyButtonStrokeLightMode</item>
<item name="ujet_colorChatQuickReplyButtonStrokeDark">@color/chatQuickReplyButtonStrokeDarkMode</item>
<item name="ujet_chatQuickReplyButtonTypeFace">Kreon-Regular.ttf</item>
<item name="ujet_chatQuickReplyButtonStrokeWidth">3dp</item>
<item name="ujet_chatQuickReplyButtonCornerRadius">3dp</item>
<item name="ujet_chatQuickReplyButtonVerticalMargin">0dp</item>
<item name="ujet_chatQuickReplyButtonHorizontalPadding">10dp</item>
<item name="ujet_chatQuickReplyButtonVerticalPadding">1dp</item>
<item name="ujet_chatQuickReplyButtonAlignment">right</item>
內容資訊卡
除了自訂即時通訊,您也可以自訂內容資訊卡。您可以使用 JSON 檔案 (請參閱 app/src/main/assets/json/ujet_styles.json 檔案中的 content_card property),或使用 ContentCardStyle 類別。
ChatStyles(
...
contentCard = ContentCardStyle(
backgroundColor = "color_reference",
cornerRadius = 8,
font = FontStyle(
colorReference = "color_reference",
size = 16,
style = "bold|italic",
family = "Roboto-Black.ttf",
),
border = BorderStyle(
color = "color_reference",
width = 2,
),
title = TextStyle(
FontStyle(
colorReference = "color_reference",
size = 18,
style = "bold|italic",
family = "Roboto-Black.ttf",
)
),
subtitle = TextStyle(
FontStyle(
colorReference = "color_reference",
size = 16,
style = "bold|italic",
family = "Roboto-Black.ttf",
)
),
body = TextStyle(
FontStyle(
colorReference = "color_reference",
size = 16,
style = "bold|italic",
family = "Roboto-Black.ttf",
)
)
)
)
網頁表單主題
你可以自訂網頁表單資訊卡和即時通訊。方法是使用 JSON 檔案 (請參閱 app/src/main/assets/json/ujet_styles.json 檔案中的 form_card 屬性),或使用 FormCardStyle 類別。
ChatStyles(
...
formCard = FormCardStyle(
backgroundColor = "color_reference",
cornerRadius = 8,
font = FontStyle(
colorReference = "color_reference",
size = 16,
style = "bold|italic",
family = "Roboto-Black.ttf",
),
border = BorderStyle(
color = "color_reference",
width = 2,
),
title = TextStyle(
FontStyle(
colorReference = "color_reference",
size = 18,
style = "bold|italic",
family = "Roboto-Black.ttf",
)
),
subtitle = TextStyle(
FontStyle(
colorReference = "color_reference",
size = 16,
style = "bold|italic",
family = "Roboto-Black.ttf",
)
),
image = ImageStyle (
height = 94,
),
)
)
問卷調查
如要變更問卷調查感謝頁面上的圖示,請將圖示上傳至應用程式的可繪項目資料夾。
請務必使用 ujet_survey_thank_you_icon 做為圖示名稱。
自訂分享螢幕畫面同意聲明對話方塊
如要自訂分享螢幕畫面同意聲明對話方塊,請實作 CoBrowseAlertProvider 抽象類別。您可以使用 DialogFragment 或 AlertDialog 導入自訂同意聲明對話方塊。
如果使用
DialogFragment,請加入兩個按鈕,一個用於接受同意聲明,另一個用於拒絕。將自訂DialogFragment例項傳遞至dialogInstance回呼。如果使用
AlertDialog,請勿將DialogFragment執行個體傳遞至dialogInstance回呼。
取得同意聲明後,請叫用 consentStatus 回呼並傳遞相應的布林值,將同意聲明傳遞至 SDK。
請使用下列程式碼範例,導入自訂同意聲明對話方塊:
class CoBrowseAlertProviderImpl : CoBrowseAlertProvider() {
// You should only implement the cobrowse consent dialog methods that you want to customize and replace the default UI.
override fun showCoBrowseSessionActivationRequestDialog(context: Context, dialogInstance: (DialogFragment) -> Unit, consentStatus: (Boolean) -> Unit) {
// Using DialogFragment for customization
val dialog = ConsentDialog.newInstance(
title = context.getString(co.ujet.android.R.string.ujet_cobrowse_session_request_alert_title),
message = context.getString(co.ujet.android.R.string.ujet_cobrowse_session_request_alert_message),
positiveButton = context.getString(co.ujet.android.R.string.ujet_cobrowse_session_request_alert_button_allow),
negativeButton = context.getString(co.ujet.android.R.string.ujet_cobrowse_session_request_alert_button_deny),
cancelable = false,
onNegativeClick = { consentStatus(false) }, // Pass consent value
onPositiveClick = { consentStatus(true) }
)
// Pass DialogFragment instance
dialogInstance(dialog)
// Using AlertDialog for customization, if you use AlertDialog instead of DialogFragment then you don't need to call `dialogInstance(dialog)`, just pass consent value using `consentStatus()`
val alertDialog = AlertDialog.Builder(context).apply {
setTitle("Co-Browse Session Request") // Set dialog title
setMessage("Allow the agent to co-browse with you?") // Set dialog message
setPositiveButton("Allow"){dialogInterface, _ ->
// Pass consent
consentStatus(true)
}
setNegativeButton("Deny"){dialogInterface, _ ->
// Pass consent
consentStatus(false)
}
}.create()
alertDialog.show()
}
override fun showCoBrowseSessionRemoteControlRequestDialog(context: Context, dialogInstance: (DialogFragment) -> Unit, consentStatus: (Boolean) -> Unit) {
// Same as showCoBrowseSessionActivationRequestDialog
}
override fun showCoBrowseSessionFullDeviceRequestDialog(context: Context, dialogInstance: (DialogFragment) -> Unit, consentStatus: (Boolean) -> Unit) {
// Same as showCoBrowseSessionActivationRequestDialog
}
override fun showCoBrowseConfirmationDialog(context: Context, dialogInstance: (DialogFragment) -> Unit, consentStatus: (Boolean) -> Unit) {
// Same as showCoBrowseSessionActivationRequestDialog
}
override fun showStopCoBrowseConfirmationDialog(context: Context, dialogInstance: (DialogFragment) -> Unit, consentStatus: (Boolean) -> Unit) {
// Same as showCoBrowseSessionActivationRequestDialog
}
}
// A generic DialogFragment class
class ConsentDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// Implement your custom dialog UI here
}
}
使用下列 API 將這項實作傳遞至 SDK:
Ujet.setCoBrowseAlertProvider(CoBrowseAlertProviderImpl())
設定網頁表單
如要設定網頁表單,請實作 UjetWebFormListener 介面的 ujetWebFormDidReceive 方法。這個方法會接收事件 (FormMessageReceived 對應) 做為參數,其中包含表單相關資訊。事件包含下列 JSON 結構:
{
"type": "form_message_received",
"smart_action_id": 1,
"external_form_id": "external_foobar",
"signature": "4868a7e1dcb5..."
}
處理事件
如要處理事件,請按照下列步驟操作:
- 從事件對應 (
smart_action_id、external_form_id和signature) 擷取相關資訊。 - 產生表單 URI 和表單資料的簽章。
- 使用
callback.onEvent(formDataEvent)將表單資料以FormDataEvent對應的形式傳遞至 SDK。 - 如果在產生 URI 或簽章時發生錯誤,請使用
callback.onError()叫用錯誤回呼。
傳遞至 SDK 的對應 (FormDataEvent) 應採用下列結構:
{
"type": "form_data",
"signature": "4868a7e1dcb5...",
"data": {
"external_form_id": "form_id",
"smart_action_id": 1,
"uri": "foobar"
}
}
簽章 (HMAC-SHA256) 必須使用資料產生,並以共用 Secret 金鑰簽署。資料的物件鍵必須先按字母順序排列,才能產生簽章,且應將相同資料傳送至 SDK。
以下程式碼範例說明如何導入網路表單事件監聽器:
class UjetWebFormListenerImpl : UjetWebFormListener {
override fun ujetWebFormDidReceive(event: Map<String, Any?>, callback: UjetWebFormCallback) {
try {
// Extract required fields from the event
val smartActionId = event["smart_action_id"]
val externalFormId = event["external_form_id"]
val signature = event["signature"]
// Simulate form URI generation (replace with actual implementation)
val formUri = "generated_form_uri"
// Prepare the data map, key should be alphabetically ordered
val data = mapOf(
"external_form_id" to externalFormId,
"smart_action_id" to smartActionId,
"uri" to formUri
)
// Generate the signature using `data`
val generatedSignature = "generated_signature"
// Create the FormDataEvent map
val formDataEvent = mapOf(
"type" to "form_data",
"signature" to generatedSignature,
"data" to data
)
// Pass the FormDataEvent to the SDK
callback.onEvent(formDataEvent)
} catch (e: Throwable) {
// If any error occurs, invoke the error callback
callback.onError()
}
}
}
使用下列 API 將這項實作傳遞至 SDK:
Ujet.setUjetWebFormListener(UjetWebFormListenerImpl())
疑難排解
發起新對話的時間超過 30 秒
請確認您是否正在回應自訂資料的委派方法。您應在收到要求時傳回有效的自訂資料,或直接透過回呼傳回空值。請參考下列程式碼。
@Override
public void onSignPayloadRequest(Map<String, Object> payload, UjetPayloadType ujetPayloadType, UjetTokenCallback tokenCallback) {
if (ujetPayloadType == UjetPayloadType.CustomData) {
tokenCallback.onToken(null);
}
}
政策聲明說明
如果您在 Google Play 管理中心收到通知,要求您針對 Android SDK 使用的服務或權限聲明政策,請使用下列其中一項說明。
宣告 Android SDK 使用的前景服務
根據 https://developer.android.com/about/versions/14/changes/fgs-types-required#remote-messaging,Google 在 Android 14 中推出前景服務類型,並強制要求在啟動前景服務時指定類型。Contact Center AI 平台 (CCAI Platform) Android SDK 會使用前景服務啟動即時通訊和通話,因此我們在處理文字訊息時,會使用 FOREGROUND_SERVICE_REMOTE_MESSAGING 服務類型進行即時通訊,並使用 FOREGROUND_SERVICE_MICROPHONE 服務類型進行通話。如果沒有這些服務類型,SDK 在 Android 14 以上版本裝置上啟動即時通訊或通話時會異常終止。
宣告 Android SDK 使用的全螢幕意圖權限
裝置鎖定時,必須具備 USE_FULL_SCREEN_INTENT 權限,才能顯示來電推播通知。系統會提醒使用者,並以全螢幕顯示來電通知 (內建的電話應用程式就是這樣通知使用者有來電)。
支援 Android 15
如要支援 Android 15,請按照下列步驟操作:
在
build.gradle(:app)中設定compileSdkVersion = 35和targetSdkVersion = 35。確認專案的 Android Gradle 外掛程式 (AGP) 版本為 8.5.1 以上。詳情請參閱「更新共用程式庫的封裝」。
安裝 Java Development Kit (JDK) 17 以上版本,使用 AGP 8.0 以上版本建構 Android 專案。詳情請參閱「執行 AGP 8.0 必須使用 JDK 17」。