Build a Core SDK App for Android

The Core SDK allows you to call all the necessary In-App Messaging APIs directly from your app. With the Core SDK, you’re in full control over the entire user experience—you tell the API when to send a message and the API tells you when a message is received.

This article applies to the following implementations:

UI SDKCore SDK

If you want to use our ready-made user interface and user experience, use the UI SDK instead.

Use the Core SDK with the Kotlin programming language since this SDK was designed to use Kotlin flows. We don’t recommend that you access the Core SDK using Java code.

Important

Create a Configuration 

Create a CoreConfiguration object using the config file that you previously downloaded from your org, or you can manually add the values from within this config file.

OPTION 1: Configure Using the Config File 

Once you’ve added the config.json file to your project, you can reference it from the code.

Use a config file
1val config = CoreConfiguration.fromFile(myContext,"configFile.json")

To learn how to download the config file from your org, see Configure an Enhanced In-App Chat Deployment in Salesforce Help. This file contains the Service API URL, the org ID, and the API name for the deployment. For example:

1{
2  "OrganizationId": "00ZZZ0000000Zzz",
3  "DeveloperName": "MyMessagingForInAppDeployment",
4  "Url": "https://zzzz.my.api.url.salesforce-scrt.com"
5}

Note

OPTION 2: Configure Manually with Config Info 

If you don’t want to use the config.json file in your project, you can configure the SDK manually using the Service API URL, the org ID, and the API name for the deployment.

Manually configure
1val url = URL("URL_TO_MY_SERVICE_API")
2val config = CoreConfiguration(url, "ORG_ID", "API_NAME_OF_DEPLOYMENT")

Get the Core Client Object 

Get the CoreClient from the CoreClientFactory using the configuration object.

Get core client object
1​​val coreClient = CoreClient.Factory.create(myContext, config)

Start the Core Instance 

Start the core instance using the correct scope. To learn more about scopes, see Coroutines and Kotlin flows in the Android documentation.

Start the core instance
1// Example of some coroutine code to get the scope.
2// See Android documentation for more info.
3private val supervisorJob = SupervisorJob()
4private val scope = CoroutineScope(Dispatchers.Main + supervisorJob)
5
6// Start listening for events using the correct scope
7coreClient.start(scope)

Create a Conversation Client 

Create a ConversationClient from the CoreClient object.

This example creates a random UUID for the conversation ID. However, if you want this conversation to persist even after the app is restarted, be sure to use the same conversation ID. Also, if you want to see this same conversation across multiple devices, in addition to using the same conversation ID, turn on user verification, which is described in the Enhance the Experience section.

Tip

Don’t use user IDs or other IDs as the ConversationID. Conversation IDs establish a permanent link with a user and are only available to the user who created it. Using a different existing ID instead of a unique ID can result in access issues or errors while developing or testing your Enhanced Chat integration. To pass existing IDs required for your flow, use the Pre-chat feature.

Note

Create a conversation client
1val uuid = UUID.randomUUID()
2val conversationClient = coreClient.conversationClient(uuid)

Handle a Pre-Chat Form 

In order to get the pre-chat fields before a conversation, call the retrieveRemoteConfiguration method from your CoreClient object. The returned remote configuration object contains a form with an array of fields. Each pre-chat field has the properties necessary for you to build your pre-chat form. After you present the pre-chat form to the user, fill in the userInput field for each pre-chat field object. Then submit the pre-chat fields from the submitRemoteConfiguration method on the ConversationClient object.

IMPORTANT: The submitPreChatData method is deprecated in SDK version 1.4. If you want to use new features in version 1.4 and later, submit pre-chat fields using the submitRemoteConfiguration method.

Important

Create a pre-chat form and submit data
1// Get the remote config object, which contains the pre-chat form
2val remoteConfig = coreClient.retrieveRemoteConfiguration()
3
4(remoteConfig as? Result.Success)?.data?.forms?.get(0)?.let { form ->
5  val field = form.formFields[0]
6
7  // Use the PreChatField attributes to render the form in your UI
8  val label = field.labels.display
9  val type: PreChatFieldType = field.type
10  // ...
11  val isRequired: Boolean = field.required
12
13  // Set the userInput value to what the end user entered in your form
14  field.userInput = "Sample User Input"
15
16  // Validate user input
17  if (field.validate() != PreChatErrorType.None) {
18    // Display error to end user
19  } else {
20    // Pass the completed form to the conversation client
21    val conversationClient = coreClient.conversationClient(uuid)
22    conversationClient.submitRemoteConfiguration(form.formFields)
23
24    // Start new conversation to submit the prechat form
25    conversationClient.sendMessage("Hello, I submitted my form and need some assistance…")
26  }
27}

To learn about hidden pre-chat fields, see Hidden Pre-Chat for Android.

Send Messages 

Send a message with the sendMessage method on the ConversationClient object.

Send a message
1conversationClient.sendMessage("It worked!")

If you see the Exception Failed (417) error on sending a message, it’s because you set the Pre-Chat Display Frequency to Every Session in the Pre-Chat Settings and a new session is being created. To fix this, call the submitRemoteConfiguration method on the ConversationClient object with your pre-chat values.

Note

Listen for Conversation Activity 

You can listen for conversation activity with the ConversationClient object and by using Android’s Paging library. To learn about paged data, see Load and display paged data in the Android documentation.

For example, to listen for conversation entries, use the conversationEntriesPaged method.

Listen for conversation entries
1val conversationEntries =
2    conversationClient.conversationEntriesPaged()
3        .filterIsInstance<Result.Success<PagingData<ConversationEntry>>>().map {
4            it.data
5        }

Use your PagingDataAdapter class to listen to the latest events.

Use the paging adapter
1conversationEntries.collectLatest {
2    myPagingAdapter.submitData(it)
3}

Your ViewHolder class can extract information from the conversation entry.

Extract text info from conversation entry
1// Extract the text from a conversation entry
2private fun getText(item: ConversationEntry?): String =
3    when (val payload = item?.payload) {
4    is EntryPayload.MessagePayload ->
5
6        when (val content = payload.abstractMessage.content) {
7        is StaticContentFormat.TextFormat -> content.text
8
9            // Handle other message formats (e.g. QuickRepliesFormat, RichLinkFormat)
10            else -> content.formatType.toString()
11        }
12
13    // Handle other entry types (e.g. ParticipantChangedPayload, AcknowledgeReadPayload)
14    else -> payload?.entryType.toString()
15}

When you receive conversation entries from various flows, they’re delivered as ConversationEntry objects. In addition to the payload, you can inspect the entryType (for example, Message) when deciding how to process the message. The payload is an instance of the EntryPayload class and it contains, in addition to the payload itself, a content field that describes the message format.

Tip

Listen for Transient Events 

To listen for transient events that come from the network, such as typing indicator feedback and network connectivity info, use Kotlin flows on ConversationClient and CoreClient.

To monitor conversation events on the ConversationClient instance, use the following properties:

  • conversation: To observe the current conversation.
  • events: To listen for events specific to this conversation.

To monitor general events on the CoreClient instance, use the following properties:

  • networkConnectivityState: To determine the network state.
  • events: To listen for general events (including events from all conversations).

For example, to listen for typing events in a particular conversation, filter on the events property.

Listen for typing events
1// Listen for progress/typing indicator events
2val events =
3    conversationClient.events.filterIsInstance<ConversationEvent.ProgressIndicator>()

When you receive events, you can extract information from the contents and pass it to the UI.

Handle typing event
1events.collectLatest {
2    // Grab the status text of the event
3    val text = "Typing Event: ${it. conversationEntry.entryType}"
4
5    // Display the text
6    Toast.makeText(requireContext(), text, Toast.LENGTH_SHORT).show()
7}

Handle Participant Roles 

The Participant interface has a role field of type string that maps to a participant role type. Participant maps to the sender field of the ConversationEntry object.

Participant Role TypeDescription
systemSet for all ParticipantChangedOperation.
userSet for all conversation entries sent by a user.
agentSet for all conversation entries sent by a rep.
chatbotSet for all conversation entries sent by a chatbot.

Enhance the Experience 

You can enhance your users’ experience by adding push notifications, passing information to Salesforce about a verified user, sending hidden pre-chat fields, adjusting chat button visibility based on business hours, and more.

For enhanced features, see Enhance the Experience for Android.

For more details about the Core SDK, see the Android Reference Documentation.