Questa pagina spiega come utilizzare l'SDK Android.
Accedi all'app di esempio
Per scaricare l'app di esempio per Android, fai clic su App di esempio per Android.
Per creare un'app di esempio utilizzando l'SDK per dispositivi mobili Android, devi disporre di quanto segue:
Chiave aziendale e secret aziendale del portale CCAI Platform.
Android 5.0 (livello API 21, Lollipop) o versioni successive.
Firebase Cloud Messaging o Google Cloud Messaging per la notifica push.
App di cui è stata eseguita la migrazione ad AndroidX.
Requisiti per l'upgrade dell'SDK Twilio
Richiede che l'SDK Twilio segua versioni specifiche se l'SDK Android è integrato utilizzando direttamente il nostro pacchetto, altrimenti questo può essere ignorato.
// Twilio VoIP SDK
api 'com.twilio:voice-android:6.1.1'
// Twilio Conversations SDK
api 'com.twilio:conversations-android:3.1.0'
Inoltre, le regole di Proguard sono già incluse nell'SDK Android per garantire che la libreria Twilio Programmable Voice non venga rimossa da ProGuard e possa essere utilizzata per la risoluzione dei problemi nel caso in cui ProGuard rimuova accidentalmente la libreria.
-keep class com.twilio.** { *; }
-keep class tvo.webrtc.** { *; }
-dontwarn tvo.webrtc.**
-keep class com.twilio.voice.** { *; }
-keepattributes InnerClasses
Per supportare le ultime versioni di Twilio, a partire dalla versione 0.34.0 dell'SDK Android, l'SDK non è più compatibile con i file binari delle applicazioni che hanno come target Java 7. Per utilizzare questa release e quelle future, gli sviluppatori devono eseguire l'upgrade delle loro applicazioni per scegliere come target Java 8. Vedi l'esempio di codice che segue:
android {
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
Ottieni la chiave e il secret dell'azienda
Accedi ad Admin Portal utilizzando le credenziali di amministratore.
Vai a Impostazioni > Impostazioni sviluppatore > Chiave aziendale e codice segreto.
Recupera la chiave aziendale e il token segreto aziendale.
Installazione
Aggiungi il repository dell'SDK Android all'impostazione Gradle per il progetto principale.
build.gradle (Project)
allprojects {
repositories {
google()
jcenter()
maven {
url "https://sdk.ujet.co/android/"
}
}
}
build.gradle (modulo: 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"
}
Configura le impostazioni aziendali
Inserisci le impostazioni della tua azienda come metadati nel file 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>
Firma JWT
Per motivi di sicurezza, le informazioni di un utente finale devono essere firmate come JWT nel tuo server.
L'app di esempio contiene APIManager per i test e devi inserire UJET_COMPANY_SECRET in mock/APIManager.java. APIManager deve implementare un metodo che avvii la chiamata asincrona per firmare il token di autenticazione JWT che restituisce il token.
In produzione, devi implementare la procedura di firma sul tuo server.
public class APIManager {
public static final String UJET_COMPANY_SECRET = "Please input your UJET_COMPANY_SECRET from Ujet developer admin page";
// ...
}
Inizializza l'SDK
Inizializza l'SDK nel metodo onCreate della classe dell'app per Android.
public class ExampleApplication extends Application implements UjetRequestListener {
@Override
public void onCreate() {
super.onCreate();
Ujet.init(this);
}
// ...
}
Autenticazione dell'utente finale
L'utente finale è il consumatore che contatta il tuo team di assistenza clienti tramite l'applicazione.
Per autenticare l'utente finale nell'applicazione, introduciamo un meccanismo di firma JWT.
L'SDK Android chiede di firmare il payload quando richiede l'autenticazione. Se la firma va a buon fine, l'applicazione scambia il JWT firmato con il token di autenticazione dell'utente finale.
In ExampleApplication devi implementare l'interfaccia UjetRequestListener per la firma del token Auth e per i dati dei clienti.
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();
}
});
}
}
}
Per saperne di più, consulta Autenticazione degli utenti finali.
Configura le notifiche push
Questa sezione descrive come attivare le notifiche push mobile.
Prepara Firebase
Devi preparare un progetto Firebase.
Se hai già un progetto, puoi utilizzare il tuo e saltare questo processo.
Crea un progetto Firebase nella console Firebase.
Scarica google-services.json da Impostazioni > GENERALE nella console Firebase.

- Recupera la chiave server da Impostazioni > CLOUD MESSAGING nella console Firebase.

Aggiungi una chiave del account di servizio
Per ricevere notifiche push, devi aggiungere una chiave dell'account di servizio alla tua app mobile. Per ottenere una chiave del account di servizio, consulta Autenticati con un service account.
Per aggiungere una chiave del account di servizio alla tua app mobile, segui questi passaggi:
Nel portale della piattaforma CCAI, fai clic su Impostazioni > Impostazioni sviluppatore. Se non vedi il menu Impostazioni, fai clic su Menu.
Vai al riquadro App mobile.
Fai clic su Modifica accanto alla tua app. Viene visualizzata la finestra di dialogo Modifica app mobile.
Nel campo Service account, inserisci la chiave del account di servizio, quindi fai clic su Salva.
Configurazione del client Android
Copia
google-services.jsonnella directory dell'app, ad esempioPROJECT_ROOT/app/google-services.json.Ottieni il token
FCMutilizzando il seguente codice: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); });Viene chiamato
FirebaseMessagingService, che viene registrato nel file manifest se il token viene aggiornato. Per saperne di più, consulta Configura un'app client Firebase Cloud Messaging su Android.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); } }Implementa
UjetRequestListener.onRequestPushTokennella classe Application.UjetRequestListener.onRequestPushTokendeve restituire il tokenFCM/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 -> { }) } }Gestisci la notifica push. Se vuoi che Contact Center AI Platform (CCAI Platform) gestisca l'elaborazione dei propri messaggi push, puoi passare i dati direttamente a
UjetPushHandler.handle().L'applicazione elabora solo i messaggi con il campo
ujet_noti_type(onoti_type, per la compatibilità con le versioni precedenti) impostato.In caso contrario, puoi scegliere di inviare solo i messaggi con
ujet_noti_typeaUjetPushHandler.handle()per l'elaborazione.
Di seguito è riportato un esempio di messaggio di notifica push:
{ "call_id" : 12345, "ujet_noti_type" : "connect_call", "noti_type" : "connect_call", "call_type" : "ScheduledCall", "fail_reason" : "none", "fail_details" : "none" }
Gestisci messaggio 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
}
}
}
Gestisci messaggio 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
}
}
}
Gestisci il messaggio GCM in GcmReceiver (metodo precedente)
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
}
}
}
Avvia la richiesta
Aggiungi la riga seguente nel punto in cui vuoi avviare l'applicazione (senza parametri):
Ujet.start(new UjetStartOptions.Builder().build());
Puoi anche avviare l'SDK Android senza la schermata iniziale.
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
.setSkipSplashEnabled(true)
.build();
Ujet.start(ujetStartOptions);
Puoi anche avviare l'SDK Android da un punto specifico del menu con questo tasto utilizzando un punto di accesso diretto:
String menuKey = "MENU_KEY";
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
.setMenuKey(menuKey)
.build();
Ujet.start(ujetStartOptions);
menuKey può essere creato con un punto di accesso diretto nel portale della piattaforma CCAI
(con ruolo di amministratore).
Vai a Impostazioni > Coda.
Seleziona una coda dalla struttura del menu.
Seleziona Crea punto di accesso diretto.
Inserisci la chiave nel modulo di testo.
Fai clic su Salva.

Puoi anche avviare l'SDK Android con un ID ticket specifico per passarlo al CRM. Questo ID ticket verrà aperto quando viene stabilita una chat o una chiamata.
String ticketId = "TICKET_ID";
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
.setTicketId(ticketId)
.build();
Ujet.start(ujetStartOptions);
Configurazione dell'SDK
Puoi configurare diverse opzioni prima di avviare l'SDK Android. Consulta la classe UjetOption. Le opzioni Numero di telefono di riserva e Sensibilità della rete descritte nella tabella seguente funzionano solo quando l'opzione Attiva fallback PSTN è attiva nel portale della piattaforma CCAI in Impostazioni > Impostazioni sviluppatore > MMA > Modifica. Quando l'opzione Abilita fallback PSTN è disattivata, non viene eseguito il fallback
alla rete PSTN. CCAI Platform utilizza la sensibilità di rete predefinita (0,85) per controllare le connessioni di rete.
| Opzione | Descrizione | Valore | Valore predefinito |
|---|---|---|---|
| Livello di log | Livello di log da stampare in Logcat. | Numero intero. Lo stesso vale per il livello di log per il log di Android. (Min: 2, Max: 7) | 5 (Log.Warn) |
| Lingua predefinita | Il codice lingua predefinito. | Stringa. Un codice lingua ISO 639. (ad es. en per l'inglese) | null |
| Numero di telefono di riserva | Il numero di telefono viene utilizzato come riserva quando internet non è disponibile o il numero di telefono rappresentativo dell'azienda non esiste nel portale di amministrazione. | Stringa. Numero di telefono. | null |
| Gestore delle eccezioni non rilevate abilitato | Abilita il gestore delle eccezioni non rilevate. Se true, l'app gestisce tutte le eccezioni dell'SDK non rilevate in fase di runtime utilizzando Thread.setDefaultUncaughtExceptionHandler. Tuttavia, se la stessa eccezione si verifica due volte, l'app si arresta in modo anomalo. |
Valore booleano. | true |
| Sensibilità della rete | La sensibilità per il controllo dello stato della rete. | Double tra 0 e 1, dove 0 è il valore meno sensibile e 1 è il più sensibile. Un valore pari a 1 utilizzerà sempre una chiamata PSTN come opzione di riserva. Se utilizzato, ti consigliamo di iniziare con un valore pari a .97. Il valore del portale in Impostazioni > Impostazioni sviluppatore > App mobile > Soglia numero di telefono di riserva sostituisce questo valore. |
0.85 |
| Modalità Buio attivata | Attiva il tema della modalità Buio. Se true, l'SDK applica un tema della modalità Buio quando l'utente attiva la modalità Buio, altrimenti ignora l'azione. |
Valore booleano. | false |
| Canale singolo abilitato | Opzione di configurazione per mostrare o bypassare la schermata di selezione del canale per un singolo canale. Se true, l'SDK mostra una singola schermata di selezione del canale anziché selezionare automaticamente il canale, anche se nella coda del menu è attivato un solo canale. |
Valore booleano. | false |
| Riduci automaticamente la visualizzazione della chiamata | Opzione di configurazione per ridurre automaticamente l'UI della schermata di chiamata iniziale per impostazione predefinita o attendere che l'utente la riduca. | Valore booleano. | false |
| Bordo dell'icona dell'agente abilitato | Opzione di configurazione per mostrare o rimuovere un bordo circolare intorno all'icona dell'agente. | Valore booleano. | false |
| Static Font Size In Picker View | Opzione di configurazione per regolare o disattivare automaticamente le dimensioni del testo degli elementi del selettore. | Valore booleano. | false |
| Nascondi allegato multimediale nella chat | Opzione di configurazione per mostrare o nascondere l'icona degli allegati multimediali nell'interfaccia utente della chat. | Valore booleano. | false |
Ignora l'autorizzazione READ_PHONE_STATE |
Se impostato su true, l'SDK non richiede l'autorizzazione READ_PHONE_STATE. Se non vuoi utilizzare le chiamate IVR in-app, imposta questo flag su true per evitare di richiedere questa autorizzazione. Inoltre, la tua applicazione deve rimuovere esplicitamente l'autorizzazione android.permission.READ_PHONE_STATE per l'SDK CCAI Platform. Tieni presente che non consigliamo di impostare questa opzione su true, perché questa autorizzazione è necessaria per il funzionamento delle chiamate IVR in-app. |
Booleano | false |
| Codice licenza Cobrowse.io (se applicabile) | Opzione di configurazione per configurare la libreria Cobrowse.io. Puoi trovare il codice licenza di Cobrowse accedendo a https://cobrowse.io/dashboard/settings e andando alla sezione Codice licenza. |
Stringa | null |
| Titolo dell'intestazione della chat personalizzata | Opzione di configurazione per personalizzare il testo del titolo dell'intestazione della chat nell'interfaccia utente della chat. | Stringa | null |
| Personalizza le risposte rapide dell'interfaccia utente della chat | Opzione di configurazione per personalizzare le risposte rapide dell'agente virtuale nella UI della chat. Le risposte rapide dell'agente virtuale sono raggruppate per impostazione predefinita, ma se vuoi visualizzarle singolarmente, puoi utilizzare questa opzione di configurazione per impostare QuickReplyButtonsStyle.INDIVIDUAL | UjetStylesOptions | QuickReplyButtonsStyle.GROUPED |
| Personalizza vari attributi dell'interfaccia utente della chat | Opzione di configurazione per personalizzare vari attributi come il carattere, il colore di sfondo, l'icona e così via. | UjetStylesOptions | null |
| Nascondi barra di stato | Opzione di configurazione per mostrare o nascondere la barra di stato. Se il valore è true, l'SDK nasconderà la barra di stato. | Booleano | false |
| Imposta la risorsa drawable della rotellina di caricamento | Opzione di configurazione per personalizzare la visualizzazione dell'indicatore di caricamento nell'app. Se non è disponibile o è null, utilizziamo la visualizzazione di caricamento predefinita. | Numero intero | null |
| Orientamento orizzontale disattivato | Disattiva l'orientamento orizzontale. Se il valore è true, l'orientamento orizzontale non viene applicato. | Booleano | false |
| Nascondi il pulsante in linea per avviare una nuova conversazione nella chat | Opzione di configurazione per mostrare o nascondere il pulsante in linea per avviare una nuova conversazione nell'interfaccia utente della chat. | Booleano | false |
| Mostra il pulsante Salta CSAT | Opzione di configurazione per mostrare o nascondere il pulsante Salta nella finestra di dialogo CSAT | Booleano | false |
| Blocca la chiusura della chat da parte dell'utente finale | Opzione di configurazione per mostrare o nascondere il pulsante Termina chat nell'UI della chat | Booleano | false |
| Nascondi il download della trascrizione della chat | Mostra o nascondi il pulsante per scaricare la trascrizione della chat nel menu Azioni della chat e nell'interfaccia utente della chat. Se aggiungi uno spazio alla stringa ujet_common_hide, il testo Hide scompare e viene visualizzata solo la Freccia indietro. |
Numero intero. Valori:
|
0
|
| Disattiva le notifiche push a livello globale | Se imposti UjetOption.setPushNotificationsAllowed su false, tutte le dipendenze delle notifiche push vengono ignorate e le notifiche push non vengono inviate agli utenti finali. |
Booleano | true |
| Nascondi Prossima disponibilità | Mostra o nascondi il messaggio Prossima disponibilità nella schermata di check-in della chat dopo l'orario di chiusura. | Booleano | false |
| Nascondi Ricomincia | Mostra o nascondi il pulsante Ricomincia nella schermata di check-in della chat fuori orario. | Booleano | 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()
)
Autorizzazioni app
L'app richiede le seguenti autorizzazioni e le richiede all'utente quando necessario.
| Autorizzazione | Descrizione |
|---|---|
| VIDEOCAMERA | Utilizzato per l'azione smart per scattare foto e registrare video |
| MICROPHONE | Consente all'app di utilizzare la chiamata VoIP tramite Twilio |
| ARCHIVIAZIONE | Consente all'app di salvare foto e video |
Preferenze della lingua
L'SDK Android utilizzerà il seguente ordine di priorità per determinare la lingua.
Lingua selezionata dalla schermata iniziale dell'app.
Lingua predefinita selezionata utilizzando
UjetOptions. Puoi impostare la lingua predefinita utilizzandosetDefaultLanguage("en")inUjetOptions. Per maggiori dettagli, consulta la sezione Lingua predefinita nella configurazione dell'SDK.Verrà utilizzata la lingua selezionata nel dispositivo (tramite Impostazioni > Generali > Lingua), se supportata dall'app.
Verrà utilizzato il dialetto più vicino alla lingua del dispositivo quando l'app non supporta la lingua del dispositivo, ma supporta il dialetto principale più vicino. Ad esempio, se l'utente ha selezionato lo spagnolo di Cuba come lingua sul dispositivo e l'app non supporta lo spagnolo di Cuba, ma supporta il dialetto principale spagnolo, verrà utilizzato lo spagnolo.
L'inglese verrà utilizzato come lingua predefinita quando la lingua del dispositivo non è supportata dall'app.
Canale preferito
Il parametro Preferred Channel ti consente di indirizzare i consumatori direttamente a un canale specifico. L'utente finale salta quindi il passaggio di selezione del canale e avvia direttamente il contatto tramite il canale specificato nel parametro Preferred Channel.
UjetStartOptions.preferredChannel
Ujet.start(new)
UjetStartOptions.Builder().setPreferredChannel
(UjetPreferredChannel.UjetPreferredChannelChat).build());
Notifiche di eventi
Se vuoi, puoi impostare UjetEventListener per ricevere notifiche di eventi dell'applicazione.
I tipi di eventi disponibili e le relative descrizioni sono elencati qui.
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());
}
});
| Tipo di evento | Descrizione | Dati inclusi nell'evento |
|---|---|---|
EmailClicked |
Si attiva quando l'utente finale fa clic sul canale email. | Dati del menu della coda |
EmailSubmitted |
Si attiva quando l'utente finale invia un'email. | Dati del menu della coda, dati inviati via email |
SessionPaused |
Si attiva quando l'utente finale riduce a icona una sessione di chat o di chiamata. | Dati di sessione |
SessionResumed |
Si attiva quando l'utente finale torna a una sessione di chat o chiamata dal background. | Dati di sessione |
SessionCreated |
Si attiva quando viene creata una sessione di chat o di chiamata. | Dati del menu della coda, dati della sessione creata |
SessionEnded |
Si attiva quando termina una sessione di chat o di chiamata. | Dati del menu della coda, dati della sessione creata, dati della sessione terminata |
SdkTerminated |
Si attiva quando l'SDK viene chiuso, anche in modo imprevisto. | Dati relativi alla terminazione dell'SDK |
ContentCardClicked |
Si attiva quando si fa clic su una scheda di contenuti. | Dati sui clic sulle schede dei contenuti |
ContentCardButtonClicked |
Si attiva quando viene fatto clic su un pulsante della scheda di contenuti. | Dati relativi ai clic sui pulsanti delle schede di contenuti |
QuickReplyClicked |
Si attiva quando viene fatto clic su una risposta rapida. | Dati sui clic sulle risposte rapide |
MessageLinkClicked |
Si attiva quando viene fatto clic su un link. | Dati sui clic sui link dei messaggi |
Dati del menu della coda
| Chiave | Tipo | Descrizione |
|---|---|---|
event_name |
Stringa | Contiene il nome dell'evento. Ad esempio, "Email selezionata". |
application |
Stringa | Contiene il nome dell'applicazione. Ad esempio, "Android". |
app_id |
Stringa | Contiene l'identificatore dell'app, che corrisponde a Context.getPackageName(). |
app_version |
Stringa | Contiene il nome e il codice della versione dell'app. Ad esempio, "0.32.0 (123)". |
sdk_version |
Stringa | Contiene la versione dell'SDK. Ad esempio, "0.32.0". |
timestamp |
Stringa | Contiene il timestamp in UTC (nel formato aaaa-MM-gg'T'HH:mm:ss'Z'). |
device_model |
Stringa | Contiene il modello del dispositivo dell'utente. Ad esempio, "Google Pixel". |
device_version |
Stringa | Contiene la versione del dispositivo dell'utente. Ad esempio, "10, Q, SDK 29". |
company |
Stringa | Contiene il nome dell'azienda. Ad esempio, "Azienda". |
menu_name |
Stringa | Contiene il nome del nodo foglia (l'ultima selezione di menu dell'utente). Ad esempio, "Sottomenu". |
menu_id |
Stringa | Contiene l'ID del nodo foglia (l'ultima selezione di menu dell'utente). Esempio: "123". |
menu_path |
Stringa | Contiene la sequenza completa dei menu selezionati dall'utente. Ad esempio, "Principale / Secondario / Sottomenu". |
menu_key |
Stringa | Contiene la chiave DAP ed è facoltativo. Ad esempio, "special_user_menu". |
Dati inviati via email
| Chiave | Tipo | Descrizione |
|---|---|---|
has_attachments |
Booleano | Restituisce True se l'email contiene allegati, altrimenti False. |
Dati di sessione
| Chiave | Tipo | Descrizione |
|---|---|---|
event_name |
Stringa | Contiene il nome dell'evento. Ad esempio, "Email selezionata". |
type |
Stringa | Contiene il tipo di sessione. Ad esempio, "chat" o "chiamata". |
timestamp |
Stringa | Contiene il timestamp in UTC (nel formato aaaa-MM-gg'T'HH:mm:ss'Z'). |
Dati della sessione creata
| Chiave | Tipo | Descrizione |
|---|---|---|
session_id |
Stringa | Contiene l'ID sessione. Ad esempio, "100". |
type |
Stringa | Contiene il tipo di sessione. Ad esempio, "chat" o "chiamata". |
end_user_identifier |
Stringa | Contiene l'identificatore dell'utente finale. Ad esempio, "Mario". |
messages_end_user |
Stringa | Contiene il conteggio dei messaggi dell'utente finale ed è incluso solo per la sessione di chat. Esempio: "3". |
messages_agent |
Stringa | Contiene il conteggio dei messaggi dell'agente ed è incluso solo per la sessione di chat. Esempio: "3". |
Dati della sessione terminata
| Chiave | Tipo | Descrizione |
|---|---|---|
agent_name |
Stringa | Contiene il nome dell'agente. Ad esempio, "Mario". |
ended_by |
Stringa | Contiene i dettagli su chi ha terminato la sessione. I valori possibili sono "agent" (quando l'agente termina la sessione), "end_user" (quando l'utente finale termina la sessione), "timeout" (quando la chat scade) o "dismissed" (quando la chat viene ignorata). |
duration |
Stringa | Contiene la durata della sessione in secondi ed è incluso solo per la sessione di chiamata. Ad esempio, "30 secondi". |
Dati relativi alla terminazione dell'SDK
| Chiave | Tipo | Descrizione |
|---|---|---|
event_name |
Stringa | Contiene il nome dell'evento. Ad esempio, "Email selezionata". |
Dati sui clic sulle schede dei contenuti
| Chiave | Tipo | Descrizione |
|---|---|---|
title |
string | Il titolo della scheda. |
title |
string | Il titolo della scheda. |
subtitle |
string | Il sottotitolo della scheda. |
body |
string | La descrizione della scheda di contenuti. |
link | string | Un link a una pagina web o un deep link. L'SDK utilizza le funzionalità del sistema operativo per aprirlo. |
event_params | dictionary | Un dizionario contenente informazioni aggiuntive sull'evento di clic. L'SDK utilizza questo valore. |
Dati relativi ai clic sui pulsanti delle schede di contenuti
| Chiave | Tipo | Descrizione |
|---|---|---|
title |
string | Il titolo della scheda. |
title |
string | Il titolo della scheda. |
link | string | Un link a una pagina web o un deep link. L'SDK utilizza le funzionalità del sistema operativo per aprirlo. |
event_params | dictionary | Un dizionario contenente informazioni aggiuntive sull'evento di clic. L'SDK utilizza questo valore. |
Dati sui clic sulle risposte rapide
| Chiave | Tipo | Descrizione |
|---|---|---|
title |
string | Il titolo della scheda. |
title |
string | Il titolo della scheda. |
link | string | Un link a una pagina web o un deep link. L'SDK utilizza le funzionalità del sistema operativo per aprirlo. |
event_params | dictionary | Un dizionario contenente informazioni aggiuntive sull'evento di clic. L'SDK utilizza questo valore. |
Dati sui clic sui link dei messaggi
| Chiave | Tipo | Descrizione |
|---|---|---|
event_name |
Stringa | Contiene il nome dell'evento, ad esempio "Clic sul link del messaggio". |
link |
Stringa | Un link a una pagina web o un deep link. L'SDK utilizza le funzionalità del sistema operativo per aprirlo. |
Invia dati personalizzati al tuo CRM
I dati personalizzati possono essere inviati agli agenti dell'assistenza e verranno visualizzati nel ticket di assistenza per la chiamata/chat in arrivo.
Esistono due metodi per inviare dati personalizzati:
Metodo firmato: firma dei dati predefinita con JWT.
Metodo non firmato: dati predefiniti con JSON normale (non consigliato).
Utilizzo del metodo firmato per inviare dati personalizzati
Per inviare dati personalizzati utilizzando il metodo firmato, implementa un metodo di firma.
Innanzitutto, recupera i dati personalizzati nell'app host, poi inviali al server per la firma. Sul tuo server, puoi aggiungere altri dati utilizzando un modulo definito. Firmali con il secret della tua azienda e poi restituiscili tramite 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));
}
// ...
}
}
Utilizzo del metodo non firmato per inviare dati personalizzati
Google consiglia di utilizzare il metodo firmato per inviare dati personalizzati nella tua applicazione. Per saperne di più, consulta Utilizzo del metodo firmato per inviare dati personalizzati.
Puoi inviare dati non firmati avviando l'SDK Android con le opzioni di avvio per impostare dati personalizzati utilizzando UjetStartOptions.Builder#setUnsignedCustomData e UjetTokenCallback deve chiamare 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);
Utilizzo di dati personalizzati non firmati per inviare la trascrizione della chat esterna
Puoi inviare la trascrizione della chat esterna alla piattaforma CCAI utilizzando dati personalizzati non firmati quando viene avviata. Utilizza UjetCustomData.putObject("external_chat_transfer", hashMapObject) per impostare i dati della trascrizione in formato JSON come segue:
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);
Formato JSON:
greeting_override: stringagent: dizionarioname: stringavatar: stringa [URL dell'avatar dell'agente, facoltativo]
transcript: arraysender: stringa ["end_user" o "agent"]timestamp: string [ie "2021-03-15 12:00:00Z"]content: arraytype: stringa [uno tra text, media]text: stringa [obbligatoria per il tipo di testo]media: dizionario [obbligatorio per il tipo di media]type: stringa [uno tra image, video]url: stringa [URL pubblico che rimanda al file multimediale]
Esempio 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"
}
]
}
]
}
Puoi utilizzare Markdown per il tipo di testo. Sono supportati i seguenti formati:
Grassetto
Corsivo
Sottolineato
Interruzioni di riga
Elenco puntato
Elenco numerato
Link
Formato dei dati personalizzato
Questa sezione mostra il formato dei dati personalizzati che possono essere trasmessi nel JWT.
JSON codificato in JWT
Il JSON deve includere iat ed exp per convalidare il JWT. L'oggetto dei dati dei clienti è il valore della chiave 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"
}
}
}
La chiave è un identificatore univoco dei dati. Il tipo è il tipo di valore.
string- Stringa JSON
number- numero intero, float
date- Formato timestamp Unix UTC con 13 cifre. (contiene millisecondi)
url- Formato URL HTTP
L'etichetta è il nome visualizzato nella pagina CRM.
Impedisci la visualizzazione di dati dei clienti
Puoi utilizzare la proprietà invisible_to_agent con un oggetto dati personalizzato per impedire la visualizzazione di dati personalizzati firmati o non firmati nell'adattatore dell'agente. Nell'esempio precedente, il numero di previdenza sociale dell'utente finale non viene mostrato nell'adattatore dell'agente perché "invisible_to_agent" : true è incluso nell'oggetto ssn.
Quando includi la proprietà "invisible_to_agent" : true con un oggetto dati personalizzato,
puoi aspettarti il seguente comportamento:
- I dati personalizzati sono inclusi nel file dei metadati della sessione.
- I dati dei clienti non sono inclusi nei record CRM.
Per saperne di più, consulta Visualizza i dati della sessione nell'adattatore dell'agente.
Proprietà dei dati riservate
Puoi inviare proprietà dei dati riservati a Contact Center AI Platform (CCAI Platform) come dati personalizzati firmati all'inizio di una sessione. Per saperne di più, consulta Inviare proprietà dei dati prenotati.
Di seguito è riportato un esempio di proprietà dei dati riservate nei dati personalizzati:
{
"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"
}
}
}
Imposta ogni valore su true o false.
reserved_verified_customer:truese ritieni che questo utente finale sia un cliente legittimo.reserved_bad_actor:truese ritieni che questo utente finale possa essere un malintenzionato.reserved_repeat_customer:truese hai stabilito che questo utente finale ha già contattato il tuo contact center.
Fallback
Puoi utilizzare UjetErrorListener per il fallback degli errori imprevisti. Se non imposti questo listener o restituisci false, l'SDK Android gestirà l'errore.
L'SDK Android reindirizzerà gli utenti al tastierino con un numero di riserva solo quando l'opzione Attiva riserva PSTN è ON in Impostazioni > Impostazioni sviluppatore > MMA > Modifica popup, altrimenti esci dall'SDK.
| Tipo di errore | Codice di errore | Trigger |
|---|---|---|
| NETWORK_ERROR | 1 | La rete non è disponibile. Tieni presente che questo errore non viene attivato quando la rete non è disponibile durante la chat, la chiamata o la schermata di valutazione. |
| AUTHENTICATION_ERROR | 100 | Si è verificato un errore imprevisto durante l'autenticazione. |
| AUTHENTICATION_JWT_ERROR | 101 | Si è verificato un errore imprevisto durante la convalida del JWT (ad es. errore di analisi). |
| VOIP_CONNECTION_ERROR | 1000 | Impossibile stabilire una connessione con il provider VoIP. Viene gestita tramite il callback dell'SDK VoIP. |
| VOIP_LIBRARY_NOT_FOUND | 1001 | È prevista la connessione di una chiamata tramite un provider VoIP, ma non è stato possibile trovarne uno. Ciò potrebbe accadere quando uno sviluppatore ha integrato l'SDK sbagliato o non ha aggiunto la libreria del provider VoIP alle sue dipendenze. |
| CHAT_LIBRARY_NOT_FOUND | 1100 | Si verifica quando non è possibile trovare la libreria di chat. Questo potrebbe accadere quando uno sviluppatore ha integrato l'SDK sbagliato o non ha aggiunto la libreria Twilio Chat alle sue dipendenze. |
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());
}
});
Deep linking
Se vuoi utilizzare le azioni smart per una chiamata IVR (PSTN), devi configurare il deep linking nel tuo progetto.
Il formato del deep linking è un URI univoco, ad esempio:
ujet:// <package_name>/smartchannel.
Inoltre, devi impostare questo link o qualsiasi URL che reindirizzi a questo link nel portale di amministrazione (Impostazioni > Gestione delle operazioni > Attiva l'invio di SMS per scaricare l'app).
Dovrai aggiungere un filtro per intent contenente il deep link nel manifest.
<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>
Resilienza della chat live
Per migliorare l'uptime della chat live, configura la resilienza della chat live. In questo modo viene aggiunto un livello multimediale di messaggistica di riserva secondario che viene utilizzato se il livello multimediale principale non funziona.
Per aggiungere questa funzionalità, aggiungi la seguente dipendenza al file build.gradle a livello di modulo:
dependencies {
implementation "co.ujet.android:chat_blue:VERSION"
}
Sostituisci VERSION con l'ultima versione dell'SDK UJET.
Modifiche al comportamento delle chiamate in arrivo
A partire dai dispositivi con versione Android 10, la chiamata in arrivo non verrà ricevuta direttamente dagli utenti finali quando l'app host è in background. Utilizziamo invece le notifiche per avvisare gli utenti delle chiamate in arrivo (anche quando lo smartphone è bloccato), offrendo loro la possibilità di accettare o rifiutare la chiamata.
Mostriamo le stesse notifiche quando l'app host è in background e lo schermo è bloccato prima dell'arrivo della chiamata in arrivo. Questa modifica del comportamento è finalizzata a rispettare le recenti limitazioni di Google relative all'avvio di attività quando l'app è in background. Il comportamento non viene influenzato quando l'app host è in primo piano o è in esecuzione su dispositivi con versioni precedenti ad Android 10.
Personalizza la sessione dell'SDK
Questa sezione descrive come personalizzare ulteriormente l'SDK.
Verifica se esiste già una sessione
Prima di avviare una sessione, utilizza il metodo descritto per verificare se esiste una sessione esistente o in corso. Se esiste, puoi chiedere all'utente finale di ripristinarlo o annullarlo.
Questo è particolarmente importante quando un utente viene modificato.
if (Ujet.getStatus() != UjetStatus.None) {
// Display alert to cancel login or resume existing session
}
Disconnetti la sessione
Consulta il metodo se vuoi disconnettere una sessione in corso.
Prima di utilizzare questo metodo, assicurati di verificare se esiste una sessione di questo tipo utilizzando Ujet.getStatus(). Se vuoi eseguire un'azione dopo che l'SDK disconnette la sessione, ad esempio mostrare un messaggio o chiudere l'app, puoi utilizzare il callback di risposta onFinished() come descritto nella sezione successiva, altrimenti imposta il callback su null.
Ujet.disconnect(new UjetResponseCallback() {
@Override
public void onFinished() {
// `onFinished()` is triggered after CCAI Platform disconnects the session.
finish(); // Finishes the activity.
}
});
Cancella i dati degli utenti finali dalla cache
È tua responsabilità svuotare la cache quando i dati relativi all'utente finale sono stati aggiornati o modificati dalla tua app. Ad esempio, se l'utente finale ha eseguito la disconnessione, richiama il metodo per rimuovere la cache per quell'utente in modo che venga avviata una nuova sessione per il nuovo utente finale al successivo avvio dell'SDK.
Ujet.clearUserData();
Nascondi l'SDK
Puoi nascondere l'SDK utilizzando il metodo Ujet.hideSDK(). Ad esempio, questo è utile quando l'SDK interferisce con l'interfaccia utente dell'app. Inizializza l'SDK utilizzando Ujet.init() prima di chiamare questo metodo. Ujet.init() restituisce true se l'SDK viene nascosto correttamente, altrimenti restituisce false. Dopo aver nascosto l'SDK, puoi avviarlo di nuovo utilizzando il metodo Ujet.start().
L'esempio seguente nasconde l'SDK:
Ujet.hideSDK();
Configura le icone dei link di deviazione esterna
Personalizza l'icona nel canale Link di deviazione esterno caricandola in una cartella drawable della tua app e assicurati di utilizzare lo stesso nome dell'icona durante la creazione del link di deviazione esterno nel portale della piattaforma CCAI in Impostazioni > Chat > Link di deviazione esterni > Visualizza link > Aggiungi link di deviazione.
Se il nome dell'icona nel portale della piattaforma CCAI non corrisponde all'icona caricata nell'app, l'SDK Android utilizzerà l'icona predefinita.
Configura l'icona Grazie dei sondaggi
Puoi personalizzare o sostituire l'icona nella pagina di ringraziamento del sondaggio caricando un'icona nella cartella drawable della tua app e utilizzando il nome file ujet_survey_thank_you_icon come nome dell'icona.
Personalizzazione della UI e delle stringhe
Questa sezione spiega come personalizzare stringhe, schede di contenuti, temi e intestazioni della chat.
Strings
Puoi personalizzare le stringhe utilizzate nell'applicazione eseguendo l'override delle chiavi per ogni stringa in 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>

Personalizzazione delle dimensioni del testo
Personalizza le dimensioni del testo del titolo, della descrizione e del selettore utilizzati nell'applicazione eseguendo l'override delle seguenti chiavi in dimens.xml.
Le dimensioni del testo personalizzabili sono descritte di seguito:
<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>

Tema
Personalizza il tema e lo sfondo seguendo questi passaggi. Il passaggio 1 riguarda il tema e il passaggio 2 lo sfondo.
Personalizza il tema eseguendo l'override delle chiavi per ogni elemento di stile in style.xml. Ad esempio,
<!--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>Puoi personalizzare il colore di sfondo nell'applicazione eseguendo l'override delle chiavi per ogni elemento di stile in style.xml. Nello screenshot è mostrato il colore di sfondo personalizzabile.
<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>
Personalizza il titolo dell'intestazione della chat
Sono disponibili opzioni per personalizzare il testo del titolo dell'intestazione della chat nella chat della tua UI.
Puoi personalizzare il testo del titolo dell'intestazione della chat utilizzando le seguenti opzioni:
<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>
Puoi personalizzare le risposte rapide dell'agente virtuale nell'interfaccia utente della chat utilizzando le seguenti opzioni:
<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>
Schede dei contenuti
Puoi aggiungere la personalizzazione delle schede di contenuti insieme alla personalizzazione della chat. Puoi farlo utilizzando il file JSON (fai riferimento a content_card property nel file app/src/main/assets/json/ujet_styles.json) o utilizzando la classe 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",
)
)
)
)
Tema del modulo web
Puoi personalizzare la scheda del modulo web insieme alla personalizzazione della chat. Puoi farlo utilizzando il file JSON (fai riferimento alla proprietà form_card nel file app/src/main/assets/json/ujet_styles.json) o utilizzando la classe 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,
),
)
)
Sondaggi
Puoi modificare l'icona nella pagina di ringraziamento del sondaggio caricando un'icona nella cartella drawable dell'app.
Assicurati di utilizzare ujet_survey_thank_you_icon come nome dell'icona.
Personalizza la finestra di dialogo per il consenso alla condivisione schermo
Per personalizzare la finestra di dialogo per il consenso alla condivisione schermo, implementa la classe astratta CoBrowseAlertProvider. Puoi utilizzare DialogFragment o AlertDialog per implementare la finestra di dialogo per il consenso personalizzata.
Se utilizzi
DialogFragment, includi due pulsanti, uno per accettare e uno per negare il consenso. Passa un'istanzaDialogFragmentpersonalizzata al callbackdialogInstance.Se utilizzi
AlertDialog, non passare l'istanzaDialogFragmental callbackdialogInstance.
Dopo aver ottenuto il consenso, trasmettilo all'SDK richiamando il callback consentStatus e trasmettendo il valore booleano di conseguenza.
Utilizza il seguente esempio di codice per implementare la finestra di dialogo per il consenso personalizzata:
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
}
}
Passa questa implementazione all'SDK utilizzando la seguente API:
Ujet.setCoBrowseAlertProvider(CoBrowseAlertProviderImpl())
Configura i moduli web
Per configurare un modulo web, implementa il metodo ujetWebFormDidReceive dell'interfaccia UjetWebFormListener. Questo metodo riceve un evento (una mappa FormMessageReceived) come parametro, contenente informazioni relative al modulo.
L'evento include la seguente struttura JSON:
{
"type": "form_message_received",
"smart_action_id": 1,
"external_form_id": "external_foobar",
"signature": "4868a7e1dcb5..."
}
Gestisci l'evento
Per gestire l'evento, segui questi passaggi:
- Estrai le informazioni pertinenti dalla mappa degli eventi (
smart_action_id,external_form_idesignature). - Genera un URI del modulo e una firma per i dati del modulo.
- Passa i dati del modulo all'SDK come mappa
FormDataEventutilizzandocallback.onEvent(formDataEvent). - Se si verifica un errore durante la generazione dell'URI o della firma, richiama il callback di errore utilizzando
callback.onError().
La mappa (FormDataEvent) passata all'SDK deve avere la seguente struttura:
{
"type": "form_data",
"signature": "4868a7e1dcb5...",
"data": {
"external_form_id": "form_id",
"smart_action_id": 1,
"uri": "foobar"
}
}
La firma (HMAC-SHA256) deve essere generata utilizzando i dati, firmati con una chiave segreta condivisa. Le chiavi degli oggetti dei dati devono essere ordinate in ordine alfabetico prima di generare le firme e gli stessi dati devono essere inviati all'SDK.
Il seguente esempio di codice mostra come implementare il listener del modulo web:
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()
}
}
}
Passa questa implementazione all'SDK utilizzando la seguente API:
Ujet.setUjetWebFormListener(UjetWebFormListenerImpl())
Risoluzione dei problemi
L'avvio di una nuova chat ha richiesto più di 30 secondi
Controlla se stai rispondendo a un metodo delegato di dati personalizzati. Devi restituire dati personalizzati validi su richiesta o semplicemente restituire null con un callback. Utilizza il seguente codice come riferimento.
@Override
public void onSignPayloadRequest(Map<String, Object> payload, UjetPayloadType ujetPayloadType, UjetTokenCallback tokenCallback) {
if (ujetPayloadType == UjetPayloadType.CustomData) {
tokenCallback.onToken(null);
}
}
Spiegazione della dichiarazione relativa alle norme
Se ricevi una notifica in Google Play Console che ti chiede di dichiarare una policy per i servizi o le autorizzazioni utilizzati dall'SDK Android, utilizza una delle seguenti spiegazioni.
Dichiara i servizi in primo piano utilizzati dall'SDK Android
Google ha introdotto i tipi di servizi in primo piano in Android 14 e ha reso obbligatorio specificarli all'avvio dei servizi in primo piano, in base a https://developer.android.com/about/versions/14/changes/fgs-types-required#remote-messaging. L'SDK Android di Contact Center AI Platform (CCAI Platform) utilizza i servizi in primo piano per avviare chat e chiamate, quindi abbiamo utilizzato il tipo di servizio FOREGROUND_SERVICE_REMOTE_MESSAGING per la chat, poiché si tratta di messaggi, e il tipo di servizio FOREGROUND_SERVICE_MICROPHONE per la chiamata. Senza questi tipi di servizi, l'SDK si arresta in modo anomalo durante l'avvio della chat o della chiamata a partire dai dispositivi con Android 14.
Dichiara l'autorizzazione per intent a schermo intero utilizzata dall'SDK Android
L'autorizzazione USE_FULL_SCREEN_INTENT è necessaria per mostrare la notifica push della chiamata in arrivo quando il dispositivo è bloccato. Avvisa l'utente finale e mostra l'avviso di chiamata a schermo intero (questo è il modo in cui l'app Telefono integrata notifica la chiamata in arrivo all'utente finale).
Supporto di Android 15
Per supportare Android 15, segui questi passaggi:
Imposta
compileSdkVersion = 35etargetSdkVersion = 35nel tuobuild.gradle(:app).Assicurati che la versione del plug-in Android per Gradle (AGP) del tuo progetto sia 8.5.1 o successiva. Per ulteriori informazioni, consulta Aggiorna il pacchetto delle librerie condivise.
Installa Java Development Kit (JDK) versione 17 o successive per creare progetti Android utilizzando AGP 8.0 o versioni successive. Per saperne di più, consulta JDK 17 richiesto per eseguire AGP 8.0.