Guia do SDK do Android

Esta página explica como usar o SDK do Android.

Acessar o app de exemplo

Para baixar o app de exemplo do Android, clique em App de exemplo do Android.

Para criar um app de exemplo usando o SDK para dispositivos móveis do Android, você precisa do seguinte:

  • Chave e secret da empresa no portal da plataforma CCAI.

  • Android 5.0 (nível 21 da API, Lollipop) ou mais recente.

  • Firebase Cloud Messaging ou Google Cloud Messaging para a notificação push.

  • O app foi migrado para o AndroidX.

Requisitos de upgrade do SDK do Twilio

Exige que o SDK do Twilio siga versões específicas se o SDK do Android for integrado diretamente usando nosso pacote. Caso contrário, isso pode ser ignorado.

// Twilio VoIP SDK
api 'com.twilio:voice-android:6.1.1'
// Twilio Conversations SDK
api 'com.twilio:conversations-android:3.1.0'

Além disso, as regras do ProGuard já estão incluídas no SDK do Android para garantir que a biblioteca Twilio Programmable Voice não seja removida pelo ProGuard e possa ser usada para resolver problemas caso o ProGuard remova a biblioteca por acidente.

-keep class com.twilio.** { *; }
-keep class tvo.webrtc.** { *; }
-dontwarn tvo.webrtc.**
-keep class com.twilio.voice.** { *; }
-keepattributes InnerClasses

Para oferecer suporte às versões mais recentes do Twilio, a partir da versão 0.34.0 do SDK do Android, o SDK não é mais compatível com aplicativos destinados ao Java 7. Para usar esta e as próximas versões, os desenvolvedores precisam fazer upgrade dos aplicativos para o Java 8. Confira o exemplo de código abaixo:

android {
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
}

Receber a chave e o secret da empresa

  1. Faça login no Admin Portal usando as credenciais de administrador.

  2. Acesse Configurações > Configurações do desenvolvedor > Chave da empresa e código secreto.

  3. Recupere o token da empresa e o código secreto da empresa.

Instalação

Adicione o repositório do SDK do Android à configuração do Gradle para o projeto raiz.

build.gradle (projeto)

allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url "https://sdk.ujet.co/android/"
        }
    }
}

build.gradle (módulo: 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"
}

Configurar as configurações da empresa

Insira as configurações da empresa como metadados no arquivo 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>

Assinatura JWT

As informações de um usuário final precisam ser assinadas como JWT no seu servidor por motivos de segurança.

O app de exemplo contém APIManager para testes. Você precisa colocar UJET_COMPANY_SECRET em mock/APIManager.java. O APIManager precisa implementar um método que inicia uma chamada assíncrona para assinar o token de autenticação JWT e retornar o token.

Em produção, é necessário implementar o processo de assinatura no servidor.

public class APIManager {
    public static final String UJET_COMPANY_SECRET = "Please input your UJET_COMPANY_SECRET from Ujet developer admin page";
    // ...
}

Inicializar o SDK

Inicialize o SDK no método onCreate da classe de aplicativo Android.

public class ExampleApplication extends Application implements UjetRequestListener {
    @Override
    public void onCreate() {
        super.onCreate();

        Ujet.init(this);
    }
    // ...
}

Autenticação de usuário final

O usuário final é o consumidor que entra em contato com sua equipe de suporte ao cliente pelo aplicativo.

Para autenticar o usuário final no aplicativo, apresentamos um mecanismo de assinatura JWT.

O SDK do Android pede para assinar o payload quando precisa de autenticação. Se a assinatura for bem-sucedida, o aplicativo vai trocar o JWT assinado pelo token de autenticação do usuário final.

Em ExampleApplication, implemente a interface UjetRequestListener para assinar o token de autenticação e dados personalizados.

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();
                    }
                });
        }
    }
}

Para mais informações, consulte autenticação de usuário final.

Configurar notificações push

Nesta seção, você vai aprender a ativar as notificações push em dispositivos móveis.

Preparar o Firebase

Prepare um projeto do Firebase.

Se você já tiver um projeto, use o seu e pule este processo.

  1. Crie um projeto do Firebase no Console do Firebase.

  2. Faça o download do google-services.json em Configurações > GERAL no Console do Firebase.

  1. Acesse Configurações > CLOUD MESSAGING no console do Firebase para encontrar a chave do servidor.

Adicionar uma chave de conta de serviço

É necessário adicionar uma chave de conta de serviço ao app para dispositivos móveis para receber notificações push. Para receber uma chave de conta de serviço, consulte Autenticar com uma conta de serviço.

Para adicionar uma chave de conta de serviço ao seu app para dispositivos móveis, siga estas etapas:

  1. No portal da plataforma CCAI, clique em Configurações > Configurações do desenvolvedor. Se o menu Configurações não aparecer, clique em Menu.

  2. Acesse o painel Apps para dispositivos móveis.

  3. Clique em Editar ao lado do app. A caixa de diálogo Editar app para dispositivos móveis vai aparecer.

  4. No campo Conta de serviço, insira a chave da conta de serviço e clique em Salvar.

Configuração do cliente Android

  1. Copie google-services.json para o diretório do app, por exemplo, PROJECT_ROOT/app/google-services.json.

  2. Extraia o token FCM usando o seguinte código:

    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 é chamado, que é registrado no manifesto se o token for atualizado. Para mais informações, consulte Configurar um app cliente do Firebase Cloud Messaging no 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);
       }
    }
    
  3. Implemente UjetRequestListener.onRequestPushToken na classe Application. UjetRequestListener.onRequestPushToken precisa retornar o token 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 -> { })
        }
    }
    
  4. Gerencie a notificação push. Se você quiser que Contact Center AI Platform (CCAI Platform) processe as próprias mensagens push, transmita os dados diretamente para UjetPushHandler.handle().

    • O aplicativo só processa mensagens com o campo ujet_noti_type (ou noti_type, para compatibilidade com versões anteriores) definido.

    • Caso contrário, você pode optar por enviar apenas mensagens com ujet_noti_type para UjetPushHandler.handle() para processamento.

    Confira abaixo um exemplo de mensagem de notificação push:

    {
        "call_id"           : 12345,
        "ujet_noti_type"    : "connect_call",
        "noti_type"         : "connect_call",
        "call_type"         : "ScheduledCall",
        "fail_reason"       : "none",
        "fail_details"      : "none"
    }
    

Processar mensagem do 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
        }
    }
}

Processar mensagem do 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
        }
    }
}

Processar mensagens do GCM no GcmReceiver (método antigo)

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
        }
    }
}

Inicie o aplicativo

Adicione a seguinte linha onde você quer iniciar o aplicativo (sem parâmetros):

Ujet.start(new UjetStartOptions.Builder().build());

Também é possível iniciar o SDK do Android sem a tela de abertura.

UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
        .setSkipSplashEnabled(true)
        .build();

Ujet.start(ujetStartOptions);

Você também pode iniciar o SDK do Android em um ponto específico do menu com essa tecla usando um ponto de acesso direto:

String menuKey = "MENU_KEY";
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
        .setMenuKey(menuKey)
        .build();

Ujet.start(ujetStartOptions);

O menuKey pode ser criado com um ponto de acesso direto no portal da CCAI Platform (com a função de administrador).

  1. Acesse Configurações > Fila.

  2. Selecione qualquer fila na estrutura de menu.

  3. Marque Criar ponto de acesso direto.

  4. Insira a chave no formulário de texto.

  5. Clique em Salvar.

Também é possível iniciar o SDK do Android com um ID de tíquete específico para transmiti-lo ao CRM. Esse ID será aberto quando um chat ou uma ligação for conectado.

String ticketId = "TICKET_ID";
UjetStartOptions ujetStartOptions = new UjetStartOptions.Builder()
        .setTicketId(ticketId)
        .build();

Ujet.start(ujetStartOptions);

Enviar dados personalizados para seu CRM

Os dados personalizados podem ser enviados aos representantes de suporte e aparecem no tíquete de suporte da chamada/chat recebido.

Há dois métodos para enviar dados personalizados:

  • Método assinado: assinatura de dados predefinida com JWT.

  • Método não assinado: dados predefinidos com JSON simples (não recomendado).

Usar o método assinado para enviar dados personalizados

Para enviar dados personalizados usando o método assinado, implemente um método de assinatura.

Primeiro, recupere os dados personalizados para o app host e envie-os ao servidor para assinatura. No seu servidor, é possível adicionar mais dados usando um formulário definido. Assine-os com o segredo da empresa e retorne-os por 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));
        }
        // ...
    }
}

Usar o método sem assinatura para enviar dados personalizados

O Google recomenda usar o método assinado para enviar dados personalizados no seu aplicativo. Para mais informações, consulte Como usar o método assinado para enviar dados personalizados.

É possível enviar dados não assinados iniciando o SDK do Android com opções de início para definir dados personalizados usando UjetStartOptions.Builder#setUnsignedCustomData e UjetTokenCallback deve chamar 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);

Usar dados personalizados não assinados para enviar uma transcrição de chat externa

É possível enviar a transcrição da conversa externa para a plataforma de CCAI usando dados personalizados não assinados quando ela é iniciada. Use UjetCustomData.putObject("external_chat_transfer", hashMapObject) para definir os dados da transcrição em formato JSON da seguinte maneira:

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: string

  • agent: dicionário

    • name: string

    • avatar: string [URL do avatar do agente, opcional]

  • transcript: matriz

    • sender: string ["end_user" or "agent"]

    • timestamp: string [por exemplo, "2021-03-15 12:00:00Z"]

    • content: matriz

      • type: string [um de texto, mídia]

      • text: string [obrigatória para o tipo de texto]

      • media: dicionário [obrigatório para o tipo de mídia]

        • type: string [uma de imagem, vídeo]

        • url: string [URL público que aponta para o arquivo de mídia]

Exemplo de 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"
            }
        ]
        }
    ]
}

Você pode usar o Markdown no tipo de texto. Os seguintes formatos são compatíveis:

  • Negrito

  • Itálico

  • Sublinhado

  • Quebras de linha

  • Lista com marcadores

  • Lista numerada

  • Links

Formato de dados personalizado

Esta seção mostra o formato dos dados personalizados que podem ser transmitidos no JWT.

JSON codificado para JWT

O JSON precisa incluir iat e exp para validar o JWT. O objeto dos dados personalizados é o valor da chave 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"
        }
    }
}

A chave é um identificador exclusivo dos dados. O tipo é o tipo do valor.

  • string

    • String JSON
  • number

    • número inteiro, ponto flutuante
  • date

    • Formato de carimbo de data/hora Unix UTC com 13 dígitos. (contém milissegundos)
  • url

    • Formato do URL HTTP

O rótulo é o nome de exibição na página do CRM.

Impedir a exibição de dados personalizados

É possível usar a propriedade invisible_to_agent com um objeto de dados personalizado para impedir que dados personalizados assinados ou não assinados sejam mostrados no adaptador do agente. No exemplo anterior, o CPF do usuário final não é mostrado no adaptador do agente porque "invisible_to_agent" : true está incluído no objeto ssn.

Ao incluir a propriedade "invisible_to_agent" : true com um objeto de dados personalizado, você pode esperar o seguinte comportamento:

Para mais informações, consulte Ver dados da sessão no adaptador do agente.

Propriedades de dados reservadas

É possível enviar propriedades de dados reservados para a Contact Center AI Platform (plataforma CCAI) como dados personalizados assinados quando uma sessão começa. Para mais informações, consulte Enviar propriedades de dados reservadas.

Confira a seguir um exemplo de propriedades de dados reservadas em dados personalizados:

  {
    "custom_data": {
      "reserved_verified_customer": {
        "label": "Verified Customer",
        "value": "VERIFIED_CUSTOMER_BOOLEAN": ,
        "type": "boolean"
      },
      "reserved_bad_actor": {
        "label": "Bad Actor",
        "value": "VERIFIED_BAD_ACTOR_BOOLEAN": ,
        "type": "boolean"
      },
      "reserved_repeat_customer": {
        "label": "Repeat Customer",
        "value": "REPEAT_CUSTOMER_BOOLEAN": ,
        "type": "boolean"
      }
    }
  }
  

Substitua:

  • VERIFIED_CUSTOMER_BOOLEAN: "True" se você considerar que esse usuário final é um cliente legítimo.
  • VERIFIED_BAD_ACTOR_BOOLEAN: verdadeiro se você considerar que esse usuário final pode ser um usuário de má-fé.
  • REPEAT_CUSTOMER_BOOLEAN: verdadeiro se você determinou que esse usuário final já entrou em contato com sua central de atendimento.

Configuração do SDK

É possível configurar várias opções antes de iniciar o SDK do Android. Consulte a classe UjetOption. As opções "Número de telefone alternativo" e "Sensibilidade da rede" descritas na tabela a seguir só funcionam quando a chave Ativar fallback da PSTN está ativada no portal da plataforma CCAI em Configurações > Configurações do desenvolvedor > MMA > Editar. Quando a chave Ativar substituição por PSTN está desativada, não fazemos substituição por PSTN. A plataforma CCAI usa a sensibilidade de rede padrão (0,85) para verificar as conexões de rede.

Opção Descrição Valor Valor padrão
Nível do registro Nível de registro a ser impresso no Logcat. Número inteiro. O mesmo vale para o nível de registro do Android. (Mín.: 2, Máx.: 7) 5 (Log.Warn)
Idioma padrão O código de idioma padrão. String. Um código de idioma ISO 639. (por exemplo, "en" para inglês) null
Número de telefone alternativo O número de telefone é usado como substituto quando a Internet não está disponível ou o número de telefone do representante da empresa não existe no portal do administrador. String. Número de telefone. null
Gerenciador de exceções não capturadas ativado Ative o gerenciador de exceções não identificadas. Se true, o app vai processar todas as exceções não capturadas do SDK no momento da execução usando Thread.setDefaultUncaughtExceptionHandler. No entanto, se a mesma exceção ocorrer duas vezes, o app vai falhar. Booleano. true
Sensibilidade à rede A sensibilidade para verificar o estado da rede. Dobro entre 0 e 1, em que 0 é o menos sensível e 1 é o mais sensível. Um valor de 1 sempre vai voltar para uma chamada PSTN. Se for usar, recomendamos começar com um valor de .97. O valor do Portal em Configurações > Configurações do desenvolvedor > Apps para dispositivos móveis > Fallback substitui esse valor. 0.85
Modo escuro ativado Ative o tema do modo escuro. Se true, o SDK vai aplicar um tema de modo escuro quando o usuário ativar esse modo. Caso contrário, a ação será ignorada. Booleano. false
Canal único ativado Opção de configuração para mostrar ou ignorar a tela de seleção de um único canal. Se true, o SDK vai mostrar uma única tela de seleção de canais em vez de selecionar automaticamente o canal, mesmo que apenas um esteja ativado na fila do menu. Booleano. false
Minimizar automaticamente a visualização da chamada Opção de configuração para minimizar automaticamente a UI da tela de chamada inicial por padrão ou esperar que o usuário faça isso. Booleano. false
Borda do ícone do agente ativada Opção de configuração para mostrar ou remover uma borda circular ao redor do ícone do agente. Booleano. false
Tamanho de fonte estático na visualização do seletor Opção de configuração para ajustar ou desativar automaticamente o tamanho do texto do item do seletor. Booleano. false
Ocultar anexo de mídia no chat Opção de configuração para mostrar ou ocultar o ícone de anexo de mídia na UI do chat. Booleano. false
Ignorar permissão READ_PHONE_STATE Se definido como true, o SDK não vai solicitar a permissão READ_PHONE_STATE. Se você não quiser usar chamadas de IVR no app, defina essa flag como true para evitar solicitar essa permissão. Além disso, seu aplicativo precisa remover explicitamente a permissão android.permission.READ_PHONE_STATE para o SDK da plataforma CCAI. Não recomendamos definir isso como true, porque essa permissão é necessária para que as chamadas de URA no app funcionem. Booleano false
Chave de licença do Cobrowse.io (se aplicável) Opção de configuração para configurar a biblioteca Cobrowse.io. Para encontrar sua chave de licença do Cobrowse, faça login em https://cobrowse.io/dashboard/settings e acesse a seção Chave de licença. String null
Título do cabeçalho do chat personalizado Opção de configuração para personalizar o texto do título do cabeçalho do chat na UI. String null
Personalizar respostas rápidas da UI do chat Opção de configuração para personalizar respostas rápidas do agente virtual na interface do chat. As respostas rápidas do agente virtual são agrupadas por padrão, mas, se você quiser mostrá-las individualmente, use essa opção de configuração para definir QuickReplyButtonsStyle.INDIVIDUAL. UjetStylesOptions QuickReplyButtonsStyle.GROUPED
Personalizar vários atributos UI interface do chat Opção de configuração para personalizar vários atributos, como fonte, cor de plano de fundo, ícone etc. UjetStylesOptions null
Ocultar barra de status Opção de configuração para mostrar ou ocultar a barra de status. Se o valor for verdadeiro, o SDK vai ocultar a barra de status. Booleano false
Definir o ícone de carregamento drawable res Opção de configuração para personalizar a visualização do spinner de carregamento em todo o app. Se não estiver disponível ou for nula, vamos usar a visualização de carregamento padrão. Número inteiro null
Orientação paisagem desativada Desative a orientação paisagem. Se o valor for verdadeiro, a orientação paisagem não será aplicada. Booleano false
Ocultar o botão inline "Iniciar nova conversa" no chat Opção de configuração para mostrar ou ocultar o botão inline "Iniciar nova conversa" na UI do chat. Booleano false
Mostrar botão para pular CSAT Opção de configuração para mostrar ou ocultar o botão "Pular" na caixa de diálogo de CSAT Booleano false
Bloquear o encerramento do chat pelo usuário final Opção de configuração para mostrar ou ocultar o botão "Encerrar chat" na UI de chat Booleano false
Ocultar o download da transcrição do chat Mostrar ou ocultar o botão "Baixar transcrição do chat" no menu de ações e na interface do usuário do chat. Se você adicionar um espaço à string ujet_common_hide, o texto Hide vai desaparecer, e apenas a seta para trás vai aparecer. Número inteiro. Valores:

0 = Mostrar em todos os lugares

1 = Ocultar do menu de opções

2 = Ocultar da tela de chat da postagem

3 = Ocultar no menu de opções e na tela após o chat.

0

UjetOption.setBlockChatTerminationByEndUser

Desativar as notificações push no nível global Definir UjetOption.setPushNotificationsAllowed como false ignora todas as dependências de notificações push e impede que elas cheguem aos usuários finais. Booleano true
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)
        .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()
        )

Fallback

Você pode usar UjetErrorListener para o fallback de erros inesperados. Se você não definir esse listener ou retornar "false", o SDK do Android vai processar o erro.

O SDK do Android vai redirecionar os usuários para o discador com um número alternativo somente quando a opção "Ativar fallback da PSTN" estiver ATIVADA em Configurações > Configurações do desenvolvedor > MMA > Editar pop-up. Caso contrário, saia do SDK.

Tipo de erro Código do erro Gatilho
NETWORK_ERROR 1 A rede não está disponível. Esse erro não é acionado quando a rede não está disponível durante uma conversa por chat ou ligação ou na tela de classificação.
AUTHENTICATION_ERROR 100 Ocorreu um erro inesperado durante a autenticação.
AUTHENTICATION_JWT_ERROR 101 Ocorreu um erro inesperado durante a validação do JWT (por exemplo, um erro de análise).
VOIP_CONNECTION_ERROR 1000 Não foi possível estabelecer uma conexão com o provedor de VoIP. Ele é processado pelo callback do SDK de VoIP.
VOIP_LIBRARY_NOT_FOUND 1001 Uma chamada deveria ser conectada usando um provedor de VoIP, mas não foi possível encontrar um. Isso pode acontecer quando um desenvolvedor integra o SDK errado ou não adiciona a biblioteca do provedor de VoIP às dependências.
CHAT_LIBRARY_NOT_FOUND 1100 Ocorre quando não é possível encontrar a biblioteca de chat. Isso pode acontecer quando um desenvolvedor integra o SDK errado ou não adiciona a biblioteca do Twilio Chat às dependências.
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());
    }
});

Permissões do app

O app requer as seguintes permissões e as solicita ao usuário quando necessário.

Permissão Descrição
CÂMERA Usado para ações inteligentes para tirar fotos e gravar vídeos.
MICROFONE Permite que o app use chamadas VoIP pelo Twilio.
ARMAZENAMENTO Permite que o app salve fotos e vídeos.

Configuração de links diretos (opcional)

Se você quiser usar ações inteligentes em uma chamada de IVR (PSTN), configure o link direto no seu projeto.

O formato de link direto é um URI exclusivo, como:

ujet:// <package_name>/smartchannel.

Além disso, você precisa definir esse link ou qualquer URL que redirecione para ele no Portal do administrador (Configurações > Gerenciamento de operações > Ativar o envio de SMS para baixar o app).

Você precisará adicionar um filtro de intent que contenha o link direto no manifesto.

<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>

Canal preferido

Com o parâmetro "Canal preferido", você encaminha os consumidores diretamente para um canal específico. O usuário final pula a etapa de seleção do canal e inicia o contato diretamente pelo canal especificado no parâmetro "Canal preferido".

UjetStartOptions.preferredChannel

Ujet.start(new)
UjetStartOptions.Builder().setPreferredChannel
(UjetPreferredChannel.UjetPreferredChannelChat).build());

Notificações de eventos

Você também pode definir UjetEventListener para receber notificações de eventos do aplicativo.

Os tipos de evento e as descrições disponíveis estão listados aqui.

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 de evento Descrição Dados incluídos no evento
EmailClicked Acionado quando o usuário final clica no canal de e-mail. Dados do menu da fila
EmailSubmitted Acionado quando o usuário final envia um e-mail. Dados do menu da fila, dados enviados por e-mail
SessionPaused Acionado quando o usuário final minimiza uma sessão de chat ou chamada. Dados de sessão
SessionResumed Acionado quando o usuário final volta para uma sessão de chat ou chamada do segundo plano. Dados de sessão
SessionCreated É acionado quando uma sessão de chat ou chamada é criada. Dados do menu da fila, dados de criação da sessão
SessionEnded Acionada quando uma sessão de chat ou chamada é encerrada. Dados do menu da fila, dados de criação e término da sessão
SdkTerminated Acionada quando o SDK é fechado, inclusive quando isso acontece de forma inesperada. Dados de encerramento do SDK
ContentCardClicked Acionado quando um card de conteúdo é clicado. Dados de cliques no card de conteúdo
ContentCardButtonClicked Acionado quando um botão de card de conteúdo é clicado. Dados de cliques no botão do card de conteúdo
QuickReplyClicked Acionada quando uma resposta rápida é clicada. Dados de cliques em respostas rápidas
MessageLinkClicked Acionado quando um link é clicado. Dados de clique no link da mensagem

Dados do menu da fila

Chave Tipo Descrição
event_name String Contém o nome do evento. Por exemplo, "E-mail clicado".
application String Contém o nome do aplicativo. Por exemplo, "Android".
app_id String Contém o identificador do app, que é igual a Context.getPackageName().
app_version String Contém o nome e o código da versão do app. Por exemplo, "0.32.0 (123)".
sdk_version String Contém a versão do SDK. Por exemplo, "0.32.0".
timestamp String Contém o carimbo de data/hora em UTC (no formato aaaa-MM-dd'T'HH:mm:ss'Z').
device_model String Contém o modelo do dispositivo do usuário. Por exemplo, "Google Pixel".
device_version String Contém a versão do dispositivo do usuário. Por exemplo, "10, Q, SDK 29".
company String Contém o nome da empresa. Por exemplo, "Empresa".
menu_name String Contém o nome do nó folha (última seleção de menu do usuário). Por exemplo, "Submenu".
menu_id String Contém o ID do nó folha (última seleção de menu do usuário). Por exemplo, "123".
menu_path String Contém a sequência completa de menus selecionados pelo usuário. Por exemplo, "Menu principal / Menu filho / Submenu".
menu_key String Contém a chave da DAP e é opcional. Por exemplo, "special_user_menu".

Dados enviados por e-mail

Chave Tipo Descrição
has_attachments Booleano Retorna "True" se o e-mail tiver anexos. Caso contrário, retorna "False".

Dados de sessão

Chave Tipo Descrição
event_name String Contém o nome do evento. Por exemplo, "E-mail clicado".
type String Contém o tipo de sessão. Por exemplo, "chat" ou "call".
timestamp String Contém o carimbo de data/hora em UTC (no formato aaaa-MM-dd'T'HH:mm:ss'Z').

Dados de criação da sessão

Chave Tipo Descrição
session_id String Contém o ID da sessão. Por exemplo, "100".
type String Contém o tipo de sessão. Por exemplo, "chat" ou "call".
end_user_identifier String Contém o identificador do usuário final. Por exemplo, "João".
messages_end_user String Contém a contagem de mensagens do usuário final e só é incluído para a sessão de chat. Por exemplo, "3".
messages_agent String Contém a contagem de mensagens do agente e só é incluído na sessão de chat. Por exemplo, "3".

Dados de encerramento da sessão

Chave Tipo Descrição
agent_name String Contém o nome do agente. Por exemplo, "João".
ended_by String Contém detalhes sobre quem encerrou a sessão. Os valores possíveis são "agent" (quando o agente encerra a sessão), "end_user" (quando o usuário final encerra a sessão), "timeout" (quando o chat atinge o tempo limite) ou "dismissed" (quando o chat é dispensado).
duration String Contém a duração da sessão em segundos e só é incluído para a sessão de chamada. Por exemplo, "30 segundos".

Dados de encerramento do SDK

Chave Tipo Descrição
event_name String Contém o nome do evento. Por exemplo, "E-mail clicado".

Dados de cliques em cards de conteúdo

Chave Tipo Descrição
title string O título do card.
title string O título do card.
subtitle string O subtítulo do card.
body string A descrição do card de conteúdo.
link string Um link de página da Web ou um link direto. O SDK usa os recursos do SO para abrir.
event_params dictionary Um dicionário que contém informações extras sobre o evento de clique. O SDK usa isso.

Dados de clique no botão do card de conteúdo

Chave Tipo Descrição
title string O título do card.
title string O título do card.
link string Um link de página da Web ou um link direto. O SDK usa os recursos do SO para abrir.
event_params dictionary Um dicionário que contém informações extras sobre o evento de clique. O SDK usa isso.

Dados de cliques em respostas rápidas

Chave Tipo Descrição
title string O título do card.
title string O título do card.
link string Um link de página da Web ou um link direto. O SDK usa os recursos do SO para abrir.
event_params dictionary Um dicionário que contém informações extras sobre o evento de clique. O SDK usa isso.

Dados de clique no link da mensagem

Chave Tipo Descrição
event_name String Contém o nome do evento, por exemplo, "Clique no link da mensagem".
link String Um link de página da Web ou um link direto. O SDK usa os recursos do SO para abrir.

Mudanças no comportamento das chamadas recebidas

A partir dos dispositivos com a versão Android 10, as chamadas recebidas não serão recebidas diretamente pelos usuários finais quando o app host estiver em segundo plano. Em vez disso, usamos notificações para alertar os usuários sobre uma chamada recebida (mesmo quando o smartphone está bloqueado), a opção de aceitar ou recusar a chamada.

Mostramos as mesmas notificações quando o app host está em segundo plano e a tela bloqueada antes da chegada da chamada. Essa mudança de comportamento tem como objetivo obedecer às restrições recentes do Google para iniciar atividades quando o app está em segundo plano. O comportamento não é afetado quando o app host está em primeiro plano ou em dispositivos com versões anteriores ao Android 10.

Personalizar a sessão do SDK

Esta seção descreve como o SDK pode ser ainda mais personalizado.

Verificar se há uma sessão

Antes de iniciar uma sessão, use o método descrito para verificar se há alguma sessão em andamento ou já existente. Se ele existir, você poderá pedir ao usuário final para retomar ou cancelar.

Isso é especialmente importante quando um usuário é alterado.

if (Ujet.getStatus() != UjetStatus.None) {
    // Display alert to cancel login or resume existing session
}

Desconectar a sessão

Consulte o método se quiser desconectar qualquer sessão em andamento.

Antes de usar esse método, verifique se uma sessão desse tipo existe usando Ujet.getStatus(). Se você quiser realizar uma ou mais ações depois que o SDK desconectar a sessão, por exemplo, mostrar uma mensagem ou fechar o app, use o callback de resposta onFinished(), conforme abordado na próxima seção. Caso contrário, defina o callback como nulo.

Ujet.disconnect(new UjetResponseCallback() {
    @Override
    public void onFinished() {
        // `onFinished()` is triggered after CCAI Platform disconnects the session.
        finish(); // Finishes the activity.
    }
});

Limpar dados do usuário final do cache

Você é responsável por limpar o cache quando os dados relacionados ao usuário final forem atualizados ou alterados no seu app. Por exemplo, se o usuário final fizer logout, invoque o método para remover o cache desse usuário. Assim, uma nova sessão será iniciada para o novo usuário final na próxima inicialização do SDK.

Ujet.clearUserData();

Ocultar o SDK

É possível ocultar o SDK usando o método Ujet.hideSDK(). Isso é útil quando o SDK interfere na interface do usuário do app, por exemplo. Inicialize o SDK usando Ujet.init() antes de chamar esse método. Ujet.init() retorna true se o SDK for ocultado com êxito e false caso contrário. Depois de ocultar o SDK, você pode iniciá-lo novamente usando o método Ujet.start().

O exemplo a seguir oculta o SDK:

Ujet.hideSDK();

Preferência de idioma

O SDK do Android vai usar a seguinte ordem de prioridade para determinar o idioma.

  1. Idioma selecionado na tela de apresentação do app.

  2. Idioma padrão selecionado usando UjetOptions. É possível definir o idioma padrão usando setDefaultLanguage("en") em UjetOptions. Consulte "Idioma padrão" na seção "Configuração do SDK" para mais detalhes.

  3. O idioma selecionado no dispositivo (em Configurações > Geral > Idioma) será usado quando for compatível com o app.

  4. O dialeto mais próximo do idioma do dispositivo será usado quando o app não for compatível com o idioma do dispositivo, mas for compatível com o dialeto principal mais próximo. Por exemplo, se o usuário selecionar "Espanhol de Cuba" como o idioma no dispositivo e o app não for compatível com essa opção, mas for compatível com o dialeto principal "Espanhol", o idioma espanhol será usado.

  5. O inglês será usado como idioma padrão quando o idioma do dispositivo não for compatível com o app.

Configurar ícones de links de evasão externos

Personalize o ícone no canal "Link de redirecionamento externo" fazendo upload dele em uma pasta drawable do seu app. Use o mesmo nome de ícone ao criar o link de redirecionamento externo no portal da plataforma CCAI em Configurações > Chat > Links de redirecionamento externo > Ver links > Adicionar link de redirecionamento.

Se o nome do ícone no portal da plataforma de CCAI não corresponder ao ícone enviado para o app, o SDK do Android usará o ícone padrão.

Configurar o ícone Agradecimento das pesquisas

É possível personalizar ou substituir o ícone na página de agradecimento da pesquisa fazendo upload de um ícone na pasta drawable do app e usando o nome de arquivo ujet_survey_thank_you_icon como nome do ícone.

Personalizar (opcional)

Esta seção descreve como personalizar valores específicos no SDK.

Strings

É possível personalizar as strings usadas no aplicativo substituindo as chaves de cada string em 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>

Configuração da pesquisa

Personalização do tamanho do texto

Personalize o título, a descrição e o tamanho do texto do seletor usados no aplicativo substituindo as seguintes chaves em dimens.xml.

Os tamanhos de texto personalizáveis são destacados:

<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

Personalize o tema e o plano de fundo seguindo estas etapas. A etapa 1 é para o tema e a etapa 2 é para o plano de fundo.

  1. Personalize o tema substituindo as chaves de cada item de estilo em style.xml. Por exemplo,

    <!--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>
    
  2. É possível personalizar a cor de plano de fundo no aplicativo substituindo chaves para cada item de estilo em style.xml. A cor de plano de fundo personalizável é mostrada na captura de tela.

    <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>
    

Personalizar o título do cabeçalho do chat

Há opções disponíveis para personalizar o texto do título do cabeçalho do chat na sua UI.

Você pode personalizar o texto do título do cabeçalho do chat usando as seguintes opções:

<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>

É possível personalizar as respostas rápidas do agente virtual na UI de chat usando as seguintes opções:

<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>

Cards de conteúdo

Você pode adicionar personalização para cards de conteúdo e para o chat. Você pode fazer isso usando o arquivo JSON (consulte content_card property no arquivo app/src/main/assets/json/ujet_styles.json) ou a 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 do formulário da Web

Você pode personalizar o card do formulário da Web e o chat. Para isso, use o arquivo JSON (consulte a propriedade form_card no arquivo app/src/main/assets/json/ujet_styles.json) ou a 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,
        ),
    )
)

Pesquisas

Para mudar o ícone na página de agradecimento da pesquisa, faça upload de um ícone para a pasta drawable do app.

Use ujet_survey_thank_you_icon como o nome do ícone.

Solução de problemas

Iniciar um novo chat levou mais de 30 segundos

Verifique se você está respondendo a um método delegado de dados personalizados. Você precisa retornar dados personalizados válidos mediante solicitação ou apenas retornar nulo com um callback. Use o código a seguir como referência.

    @Override
    public void onSignPayloadRequest(Map<String, Object> payload, UjetPayloadType ujetPayloadType, UjetTokenCallback tokenCallback) {
        if (ujetPayloadType == UjetPayloadType.CustomData) {
            tokenCallback.onToken(null);
        }
    }

Explicação da declaração de política

Se você receber uma notificação no Google Play Console pedindo para declarar uma política para os serviços ou permissões usados pelo SDK do Android, use uma das explicações a seguir.

Declarar serviços em primeiro plano usados pelo SDK do Android

O Google introduziu os tipos de serviços em primeiro plano no Android 14 e exigiu que eles fossem especificados ao iniciar esses serviços, de acordo com https://developer.android.com/about/versions/14/changes/fgs-types-required#remote-messaging. O SDK do Android da Contact Center AI Platform (Plataforma CCAI) usa serviços em primeiro plano para iniciar chat e chamadas. Por isso, usamos o tipo de serviço FOREGROUND_SERVICE_REMOTE_MESSAGING para chat, já que estamos lidando com mensagens de texto, e o tipo de serviço FOREGROUND_SERVICE_MICROPHONE para chamadas. Sem esses tipos de serviço, o SDK vai falhar ao iniciar um chat ou uma chamada em dispositivos com a versão 14 do Android ou mais recente.

Declarar a permissão de intent para tela cheia usada pelo SDK do Android

A permissão USE_FULL_SCREEN_INTENT é necessária para mostrar a notificação push de chamada recebida quando o dispositivo está bloqueado. Ele alerta o usuário final e mostra a notificação de chamada recebida em tela cheia. É assim que o app de telefone integrado notifica o usuário final sobre a chamada recebida.

Compatibilidade com o Android 15

Para oferecer suporte ao Android 15, siga estas etapas:

  1. Defina compileSdkVersion = 35 e targetSdkVersion = 35 no seu build.gradle(:app).

  2. Verifique se a versão do Plug-in do Android para Gradle (AGP) do projeto é 8.5.1 ou mais recente. Para mais informações, consulte Atualizar o pacote das bibliotecas compartilhadas.

  3. Instale o Java Development Kit (JDK) versão 17 ou mais recente para criar projetos do Android usando o AGP 8.0 ou mais recente. Para mais informações, consulte JDK 17 necessário para executar o AGP 8.0.