50 Oracle iOS

Using the Oracle iOS SDK for Oracle Digital Assistant, you can integrate your digital assistant with iOS apps. The SDK connects to the Oracle Chat Server, the intermediary between the Oracle iOS channel configured in Oracle Digital Assistant and the client. The chat server then passes messages to the skill for processing and delivers the skill's response to the client.

What Do You Need?

  • An Oracle iOS Channel. Creating the channel generates the Channel ID and the Secret Key that you need to initialize the chat app.
  • The URL of the Oracle Chat Server.
  • The Oracle iOS SDK (located under Oracle Native Client SDKs for OCI Native Environments) from Oracle Technology Network’s ODA and OMC download page. Download this ZIP and extract it to your local system. This ZIP includes a user guide that describes the SDK's functions.
  • Starting with Version 22.04, the supported version of Swift is 5.6. The minimum requirements for this version are:
    • Swift Version: 5.5
    • Target iOS Version: 12.0 or higher
    • Xcode Version: 13 or higher

    Note:

    If you want your app to work with earlier versions, keep in mind that we haven't tested these and therefore can't guarantee their compatibility.

Create the Oracle iOS Channel

You can configure the channel to connect to the Oracle Chat Server in two modes: unauthenticated mode and authenticated mode (to protect access to the channel).
  • Unauthenticated mode – Use the unauthenticated mode when the client can't generate signed JWT tokens, when no authentication mechanism is in place, or when the client widget is already secured and visible to authenticated users.
  • Authenticated mode – Authentication is enforced using JSON Web Tokens (JWT). The customer's backend server generates the JWT token, which is then passed to the Oracle iOS SDK. This token is used for each request to an ODA speech, text, or attachment server.

    Note:

    To protect access to the channel, the token must always be generated by a remote server. It must never be generated within by the client app.
    When the app needs to connect to an ODA server, it first requests the token from the backend server and then adds it to the Authorization header. The ODA server validates the token, evaluates the claims, and then either opens the socket or rejects the connection.
    The JWT Token has the following claims: channelId and userId, and the claim names iat (issued at time), and exp (expiration time). iat signifies the time at which the token was issued. This must a number that represents the seconds that have elapsed since the UNIX epoch. exp must be a number representing the seconds that have elapsed since the UNIX epoch. We recommend setting the expiration time to at least 30 minutes after the issued at time (iat). The token header looks something like this:
    {
    
     "alg": "HS256",
    
     "typ": "JWT"
    
    }
    An example token body looks something like this:
    {
    
      "iat": 1569828182,
    
      "exp": 1569831782,
    
      "channelId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    
      "userId": "John"
    
    }

    Note:

    The token illustrated by this example is not signed. The actual tokens are signed by channel's Secret Key.

Configure the Oracle iOS Channel

To configure the Oracle iOS channel:
  1. Choose Development, then Channels from the menu.
  2. Choose Users.
  3. Click Add Channel and then Oracle iOS as the channel type.
  4. Complete the dialog:
    • Enter the channel name.
    • For authenticated connections:
      • Switch on the Client Authentication Enabled toggle to determine whether the SDK is connecting to a client authentication-enabled channel.
      • In the Max. Token Expiration (Minutes) field, set the maximum amount of time for the JWT token.
      • Set the Session expiration time.
    • For unauthenticated connections:
      • Switch off Client Authentication Enable toggle.
      • Set the Session expiration time.
    • Click Create. Oracle Digital Assistant will generate the Channel ID and the Secret Key that you need to initialize the SDK. Keep these close at hand because you'll need them when configuring the HTML page to host the chat widget.
  5. Route the channel to your skill or digital assistant.
  6. Switch Channel Enabled to On.

Add the SDK to the Project

The frameworks are bundled into a single .xcframework file.
  1. Download the ODA Client SDK for iOS and extract it to your local system.
  2. Add the .xcframework files to the Frameworks file in your Xcode project. Choose the set of frameworks from the appropriate folder depending on where you want to run the app (simulator or actual device). You can drag and drop the files into the Frameworks file or you can add them as follows:
    1. Click File > Add Files to "<project name>".
    2. Choose the .framework files that you want to add depending on where you want to run the app (simulator or actual device).
    3. Make sure to that Copy items if needed (located under Destinations) is selected.
    4. Alternatively, you can drag and drop the .framework files into the project file in Xcode.
  3. After you've added the files:
    • Make sure Copy items if needed for the Destination property is selected.
    • Make sure that Add to Targets is selected for the project.
  4. Embed and sign the frameworks in the Frameworks, Libraries, and Embedded Content category in the General tab. (This may vary according to the version of Xcode that you're using.) Make sure the Targets option is selected.
  5. Add the following keys in the project's Info.plist file:
    • Privacy - Location Always and When In Use Usage Description or <key>NSLocationAlwaysUsageDescription</key> and the corresponding <string></string> in the source code.
    • Privacy - Location When In Use Usage Description or <key>NSLocationWhenInUseUsageDescription</key> and the corresponding <string></string> in the source code.
    • Privacy - Microphone Usage Description or <key>NSMicrophoneUsageDescription</key> and the corresponding <string></string> in the source code.
    • Privacy - Camera Usage Description or <key>NSCameraUsageDescription</key> and the corresponding <string></string> in the source code.
    • Privacy - Photo Library Usage Description or <key>NSPhotoLibraryUsageDescription</key> and the corresponding <string></string> in the source code.
  6. To open a location in Google maps instead of Apple maps when a user taps a map view in a location message, declare the URL schemes used by the Maps SDK for iOS in the app's Info.plist file as described in the Google Maps SDK for iOS documentation.
  7. To enable users to download attachments that are part of a skill response, set the Application Supports iTunes file sharing key (UIFileSharingEnabled) to YES and the Support opening documents in place key (LSSupportsOpeningDocumentsInPlace) to YES in the Info.plist file.

Initialize the SDK in Your App

You can use the following code to initialize the chat view.
// Import the SDK
import BotClientUISDK

public class ViewController: UIViewController {

    // Declare a global BotsViewController variable in your app view controller class
    public var chatViewController: BotsViewController?

    override func viewDidLoad() {

        // Obtain a shared instance of BotsViewController from BotsUIManager
        chatViewController = BotsUIManager.shared().viewControllerInstance()

        // Specify the color changes if any in a particular component. Make sure you set all the required colors in BotsProperties before adding the chat view to the view controller.

        // Add the chatViewController to your navigationController
        self.navigationController?.pushViewController(chatViewController!, animated: false)

        // Obtain a shared instance of BotsManager
        let botsManager = BotsManager.shared()

        // If you require access to callback methods provided in AuthenticationProvider. Make sure your class conforms to BotsMessageServiceDelegate
        botsManager.authenticationTokenProvider = self

        // Initialize a BotsConfiguration object and set feature flags if required.
        var botsConfiguration = BotsConfiguration(url: url, userId: userId, channelId: channelId)

        // Initialize the configuration in botsViewController. Make sure you set all the feature flag values before passing the botsConfiguration to initConfiguration.
        chatViewController?.initConfiguration(botsConfiguration: botsConfiguration)

        // If you require access to callback methods provided in BotsMessageServiceDelegate. Make sure your class conforms to BotsMessageServiceDelegate
        botsManager.delegate = self

        // If you require access to callback methods provided in BotsEventListener. Make sure your class conforms to BotsEventListener
        botsManager.botsEventListener = self

        // Initialize and establish connection to the chat server
        botsManager.initialize(botsConfiguration: botsConfiguration, completionHandler: { (connectionStatus, error) in
            if error != nil {
                print ("Error: \(error.localizedDescription)")
            } else {
                print ("Connection Status: \(connectionStatus)")
            }
        })
    }
}

App Development

Initialize the Feature Flag Settings

Initialize BotsConfiguration object using one of its constructors.
  • clientAuthDisabled
    • BotsConfiguration(url: String, userId: String, channelId: String)
      • Parameters:
        • url - The Oracle Chat Server URL. This cannot be null.
        • userId - The unique identifier for the user. This cannot be null.
        • channelId - The Oracle iOS Channel ID. This cannot be null.
      • When the userId not provided (a randomly generated value is instead)
        • url - The Oracle Chat Server URL. This cannot be null.
        • channelId - The Oracle iOS Channel ID. This cannot be null.
  • clientAuthEnabled
    • BotsConfiguration(url: String, authToken: String)
      • Parameters:
        • url - The Oracle Chat Server URL. This cannot be null.
        • authToken - The authentication token for establishing a connection with an authentication-enabled channel. This cannot be null.
For example:
// Initialize a BotsConfiguration object
var botsConfiguration = BotsConfiguration(url: chatServerUrl, authToken: token)
 
// Set the feature flag values if the desired values are different from the default values
botsConfiguration.showConnectionStatus = true
botsConfiguration.enableBotAudioResponse = true
botsConfiguration.disablePastActions = "none"

Network Configuration

Property Name Description Required? Default Value
url The URL of the Oracle Chat Server Yes N/A
channelId The ID of the Oracle iOS channel. Yes N/A
userId The unique identifier for user. This value gets initialized by the SDK if not provided. No A randomly generated value
authToken The authentication token for establishing a connection with an authentication-enabled channel. Yes N/A

Feature Flags

Property Description Required? Default Value
disablePastActions A field for disabling the button clicks on the messages that a user has already interacted with. The allowed values are all, none, and postback. The behavior enabled by this property is independent of the digital assistant-level configuration for disabling the selection of past actions. You need to set the two separately. No all
displayPreviousMessages Enables, or disables, the user's local conversation history. No false
enableAgentSneakPreview If enabled, the agent can view the user message as it is being typed, even before the user sends the message. Otherwise, ... is sent to the agent. No false
enableAttachment Configures attachment sharing in the chat app. No true
enableAttachmentSecurity When set to true, extra headers are passed to the attachment upload requests to ensure that they can't be downloaded without passing a valid signed JWT token as an authorization header.

Note: Do not enable this setting if the skill connects to an ODA instance that's Version 20.08 or runs on any version prior to 20.08. This property only applies to client auth-enabled connections to Versions 20.12 and higher of the ODA platform.

No false
enableAutoSendSpeechResponse When set to true (the default), the user's speech response is automatically sent to the chat server (and rendered as a sent message in the chat window). When set to false, the user's speech response is rendered in the message text field before it's sent to the chat server, allowing the user to modify it before sending it manually, or delete the message. No true
enableClearMessage Enables the clear message button in the chat widget header. No false
enableDefaultClientResponse When set to true, the client displays default responses when the skill response has been delayed, or when there's no response from the skill. No false
enableEndConversation Enables the user to end the conversation and reset the chat session. It also clears the local conversation history, disconnects from the chat server, and minimizes the widget. No true
enableSendTypingStatus Controls the sending of the user typing status. No false
enableSpeechRecognition Enables the microphone button. No false
enableSpeechSynthesis Enables the skill responses to be read aloud. By setting this flag to true, you enable the skill's responses to be read aloud using Swift API. No false
enableTimestamp Enables the timestamp for messages. You can set the timestamp display mode as absolute or relative using the timestampMode setting. No true
headerLogo Passes a UIImage object, which is placed on the header. The default alignment is on the left side of the header. To place it on the right, set the headerLogoAlignment property to NSTextAlignment.right. No N/A
headerLogoAlignment Sets the alignment of the header logo, if passed. No NSTextAlignment.left
initSpeechSynthesisMuted Sets the default state of BotAudioResponse as muted or unmuted. No true
initUserHiddenMessage A user text message that's used to initiate a conversation. This message, which is sent when chat widget is ready, does not actually display in chat. No N/A
initUserProfile Initializes the user profile before the start of the conversation. The format of the profile payload must be ["profile": […] ]. For example:
initUserProfile = ["profile": ["givenName": "First", "surname": "Last", "email": "first.last@example.com", "properties": ["lastOrderedItems": "1 medium pepperoni"]]]
This function updates the user context before the initial "hidden" message is sent by initUserHiddenMessage to start the conversation. As a result, the user profile can be reflected in the first response message to the user. For example, the skill can greet the user with a message like "Welcome back, John Smith! Your last order was a medium pepperoni pizza."
No N/A
multiLangChat Enables the chat widget to both detect a user's language and allow the user to select a preferred language from a dropdown menu in the header for conversation.    
reconnectMaxAttempts The number of attempts made by the chat widget to reconnect when the initial connection fails. No 5
sharePopupConfiguration Allows the user to choose the options available as part of the attachment menu. The default value is set to a list of all options. No [.photoAndVideoLibrary, .files, .camera]
showConnectionStatus Enables the connection status to display in the chat widget header. No false
showTypingStatus Displays the typing indicator when waiting for skill's response. No true
speechLocale The expected locale of the user's speech that's used for voice recognition. US English ('en-US') is the default locale. The other supported locales are: Australian English ('en-au'), UK English ('en-uk'), French ('fr-fr'), German ('de-de'), Italian ('it-it'), Brazilian Portuguese ('pt-br'), and Spanish ('es-es'). The speech locale can be set dynamically by calling the setSpeechLocale('<locale>') API. Voice recognition will not work if an unsupported locale has been passed. No en-us
speechSynthesisVoicePreferences Matches the provided preferences based on both the language-locale and voice name. If no match is found, then the default voice for the given language-locale is used. In the latter case, the Apple API finds the best match with the given language-locale. No N/A
timestampFormat Formats the delivery timestamp that accompanies messages. The timestamp format should be supported by the Swift DateFormatter. No E MMM d, HH:mm a
timestampMode If you enable timestamps by setting enableTimestamp to true, you can use set the timestamp mode as either absolute timestamps that appear on each message, or as a relative timestamp that appears only on the latest message.
  • TimestampMode.default – Sets an absolute timestamp on each message.
  • TimestampMode.relative – The timestamp displays before the first message of the day as an absolute timestamp in a header, and then as a relative timestamp for the new messages as an updating timestamp indicating the time passed since the message was added in the conversation. The relative timestamp updates at set intervals until a new message is received.
No TimestampMode.relative
title Sets the title of the app, which is displayed in the app bar. No N/A
ttsService An instance of type TTSService which used for injecting a text-to- speech (TTS) service. Applicable only if enableSpeechSynthesis is set to true. No  
typingStatusInterval The interval, in seconds, to throttle the typing event and the sending of the typing status. No 3
typingStatusTimeout Sets the timeout, in seconds, to hide the typing status indicator when no response has been received from the chat server. No 30 secs

Strings

Configure strings by adding the following key = value pairs in the app's <language-code>.iproj/Localizable.strings file.
Key Description Default Value
connectionFailureMessage The message that displays after the number of attempts set by reconnectMaxAttempts have been exhausted. Sorry, the assistant is unavailable right now. If the issue persists, contact your help desk.
connectionRetryLabel The default string for the retry button that displays with connectionFailureMessage. Try Again
end_conversation_action_yes The text for the confirm button in the end session confirmation prompt. Yes
end_conversation_alert_message The message body of the end conversation confirmation prompt. This will also clear your conversation history
end_conversation_alert_no The text for the decline button in the end session confirmation prompt. No
end_conversation_alert_title The title for the end conversation confirmation prompt. Are you sure you want to end the conversation?
odais_access_label_audio_attachment The accessibility label for an audio attachment message audio attachment
odais_access_label_button_attach The accessibility label for the upload attachment button. Upload attachment
odais_access_label_button_audio_reponse_off The accessibility label for the muted volume button Unmute audio response
odais_access_label_button_audio_reponse_on The accessibility label for the unmuted volume button. Mute audio response
odais_access_label_button_back The accessibilty label for the back button. Go back
odais_access_label_button_card_navigation_left The accessibility label for the left navigation button for the horizontal card view. Card navigation right
odais_access_label_button_card_navigation_right The accessibility label for the right navigation button for the horizontal card view. Card navigation left
odais_access_label_button_clear The accessibilty label for the clear message button Clear messages
odais_access_label_button_keyboard The accessibility label for the keyboard button. Enter message
odais_access_label_button_overflow The accessibility label for a overflow menu button. Open Menu
odais_access_label_button_select_language The accessibility label for select language button. Select Language
odais_access_label_button_send The accessibility label for the send button Send message
odais_access_label_button_speak The accessibility label for the mic button Speak message
odais_access_label_card_desc The accessibility label for a card description that's followed by the text card description
odais_access_label_card_title The accessibility label for a card title that's followed by the text card title
odais_access_label_chat_status The accessibility label for the chat status which is followed by the status string Chat status
odais_access_label_chat_title The accessibility label for the chat title which is followed by the chat title string Chat title
odais_access_label_file_attachment The accessibility label for a file attachment message file attachment
odais_access_label_footer_text The accessibility label for a footer text that's followed by the text footer text
odais_access_label_header_text The accessibility label for a header text that's followed by the text header text
odais_access_label_image_attachment The accessibility label for an image attachment message image attacment
odais_access_label_location_message The accessibility label for a location message that's followed by the location message title and the latitude and longitude location message
odais_access_label_pause The accessibility label for the pause button. Pause
odais_access_label_play The accessibility label for the play button Play
odais_access_label_skill The accessibility label for a skill message payload read by VoiceOver (the iOS Accessibility feature). This label is then appended with the message specific label. Skill
odais_access_label_text_message The accessibility label for a text message that's followed by the text text message
odais_access_label_user The accessibility label for a user message payload read by VoiceOver (the iOS Accessibility feature). This label is then appended with the message specific label. User
odais_access_label_video_attachment The accessibility label for a video attachment message video attachment
odais_access_label_webview_clear_button The accessibility label for the WebView clear button in the in-widget webview. Close webview
odais_access_label_webview_title The default accessibility label for the title of the in-widget Webview. Webview title
odais_alert The title of the alert message displayed for speech and file-related errors. Alert
odais_camera The action text that appears on the attachment popup for using the device's camera. Camera
odais_camera_permission_denied The error message that's displayed when camera access is not allowed. Camera permission denied.
odais_chat_title The title of the app that's displayed on the app bar. Digital Assistant
odais_check_url The error message displayed for a broken link in the webview. Please check the url!
odais_clear_chat The title of the clear chat button in the overflow menu. Clear Chat
odais_connected The status text that displays when the connection between chat widget and the Oracle chat server has been established. Connected
odais_connecting The status text that displays while the chat widget connects to the Oracle chat server. Connecting
odais_default_greeting_message The default greeting response. Hey, Nice to meet you! Allow me a moment to get back to you.
odais_default_sorry_message The default response when the wait time for message expires. I'm sorry. I can't get you the right content. Please try again.
odais_default_wait_message The default response that displays while waiting for the skill message. I'm still working on your request. Thank you for your patience!
odais_disconnected The status text that displays when the connection between the chat view and the Oracle chat server has closed. Disconnected
odais_done The label text for the button that closes the chat view. Done
odais_download_attachment_folder The name of the folder created inside the applications folder for saving attachments. The default value is an empty string. An empty string.
odais_error The title of the webview-related error and alert messages. Error
odais_fail_to_load The error message displayed when the page can't load in in the webview. The text inside the curly braces ({}) will be linkified with the link to open in the default browser. Sorry, we can't open this page in the chat window. Click {here} to open it in your browser.
odais_file_not_supported The alert message displayed when the user selects file type that's not supported for attachments. File type not supported
odais_file_size_warning The alert message that's displayed when the file chosen for attachment exceeds the max attachment size limit. The text {0} is replaced by the max attachment size limit set. The default max attachment size limit is 25MB. You can only attach files of size up to {0}MB.
odais_files The action text that appears on the attachment popup for choosing a file from storage. Files
odais_gallery_permission_denied The alert message displayed when permission to the gallery has not been granted. You don't have permission to access gallery.
odais_language_ar The default string for displaying the Arabic language in the drop-down menu unless otherwise provided. Arabic
odais_language_de The default string for displaying the German language in the drop-down menu, unless otherwise provided. German
odais_language_detect The default string for displaying Detect Language in the drop-down menu, unless otherwise provided. Detect Language
odais_language_en The default string for displaying the English language in the drop-down menu, unless otherwise provided. English
odais_language_es The default string for displaying the Spanish language in the drop-down menu, unless otherwise provided. Spanish
odais_language_fr The default string for displaying the French language in the drop-down menu, unless otherwise provided. French
odais_language_it The default string for displaying the Italian language in the drop-down menu, unless otherwise provided. Italian
odais_language_nl The default string for displaying the Dutch language in the drop-down menu, unless otherwise provided. Dutch
odais_language_pt The default string for displaying the Portuguese language in the drop-down menu, unless otherwise provided. Portuguese
odais_location_disabled The error message that's displayed when location services are disabled. Location services not enabled. Please enable the Location Services switch in Settings > Privacy.
odais_location_fetch_error The error message that's displayed when the SDK is not able to fetch the current device location. Error in getting device location. Please check location settings or try again.
odais_location_permission_denied The error message that's displayed when location access is not allowed. Location Permission Denied.
odais_mute The title of the mute button in the overflow menu. Mute
odais_no_speech_error The alert message that'sdisplayed when no audio content is sent to the speech server (the user hasn't spoken). Could not detect the voice, no message sent.
odais_notification_title The title displayed on the notifications bar. OracleChatBot
odais_ok The label text for the button that closes alert and error messages. Ok
odais_photo The action text that appears on the attachment popup for choosing a file from phone's gallery. Photo & Video Library
odais_select_language The title of the select language button in the overflow menu. Select Language
odais_speak_your_message The placeholder text for the user message input field in speech mode Start speaking
odais_speech_cancel The button label text on the speech popup for cancelling the sending of recorded audio to the speech server. CANCEL
odais_speech_error The alert message that's displayed when the audio cannot be recorded. Error in voice recognition. Please try again later.
odais_speech_permission_denied The error message displayed when microphone usage is not allowed. Permission_Denied
odais_speech_start The text displayed on the speech popup indicating that the user can now start speaking. Listening...
odais_speech_unsupported_locale The error message displayed when the set speech locale is not supported by the speech server. The set speech locale is not supported. Cannot start recording.
odais_stars_rating The message that's read aloud when the user clicks a feedback button while in accessibility mode Rate {0} star
odais_subtitle The subtitle of the chat widget that's displayed below the title in the header . If showConnectionStatus is set to true, and the subtitle is set as well, the subtitle is displayed instead of the connection status. N/A
odais_timestamp_days The relative timestamp that displays every day since the previous message was received. {0} is replaced by the number of days that have passed. {0}d ago
odais_timestamp_hours The relative timestamp that displays every hour for the first 24 hours after the previous message was received. {0} is replaced by the number of hours that have passed. {0}hr ago
odais_timestamp_minutes The relative timestamp that displays every minute since the last message was received. {0} is replaced by the number of minutes that have passed. {0}min ago
odais_timestamp_months The relative timestamp that displays every month since the previous message was received. {0} is replaced by the number of months that have passed. {0}mth ago
odais_timestamp_now The relative timestamp that displays for a new message. Now
odais_timestamp_seconds The relative timestamp that displays ten seconds after the message has been received and before 60 seconds has elapsed since the last message was received. A few seconds ago
odais_timestamp_years The relative timestamp that displays each year after the previous message was received. {0} is replaced by the number of years that have passed. {0}yr ago
odais_too_much_speech_error The alert message that's displayed when too much audio content is sent to the speech server at once (the user speaks too much). Too much voice input to recognize. Cannot generate recognized text.
odais_type_your_message The placeholder text for the user message input field Enter message
odais_unmute The title of the unmute button in the overflow menu. Unmute
odais_upload_attachment The text that's displayed on the bubble indicating that an attachment is being uploaded. Uploading attachment
odais_upload_attachment_error The error message that displays when an attachment cannot be uploaded. Error in uploading attachment
odais_zero_byte_file_warning The alert message that's displayed when the selected file has zero (0) bytes. Files of size zero bytes can not be uploaded.

UI Properties and Colors

You can modify the colors for the following components by using BotsProperties.<component name> = <UIColor type>. As described in Initialize the SDK in Your App, you must set all of the colors in BotsProperties before adding the chat view to the view controller.

Component Description Values
ActionBorderColor The border color for an action button 161513.withAlphaComponent(0.50)
ActionButtonColor The color for an action button UIColor.clear
ActionLabelTextColor The text color for an action label #161513
AgentAvatarBackgroundColor The background color of the avatar layout when the agent avatar has not been provided and the agent name initials display in its place #A890B6
AgentAvatarTextColor The text color of the agent name initials that display inside the agent avatar layout. UIColor.white
AgentNameTextColor The text color used for the agent name that displays above the agent messages. #161513.withAlphaComponent(0.65)
AttachmentBackgroundColor The background color of the attachment messages. UIColor.white
AttachmentBorderColor The background color of the attachment messages. #161513
AttachmentIconColor The color of the icons in attachment messages. #161513
AttachmentTextColor The text color of the attachment messages. #161513
BotMessageColor The background color for text, attachment, and location messages sent by the skill UIColor.white
BotTextColor The color for the text in a text message sent by the skill #161513
CardActionBorderColor The order color of a card action button #161513.withAlphaComponent(0.50)
CardActionButtonColor The color of a card action button UIColor.clear
CardActionLabelTextColor The text color of a card action label UIColor.white
CardBackgroundColor The background color for a card UIColor.white
CardDescriptionTextColor The text color for a card description #161513
CardNavigationArrowColor The color of the navigation button arrows in a horizontal card view #161513
CardNavigationButtonColor The color of the navigation buttons in horizontal card view #FBF9F8
CardTitleTextColor The text color for a card title #161513
ChatBackgroundColor The color for the chat view background #F5F4F2
conversationBeginPosition Sets the starting point of the conversation at the top or the bottom. Values are top and bottom. The default is bottom.
EnableArrowsForHorizontalCards Enables navigation arrows for horizontal card view when set to true. Disables them when set to false. false
FooterColor The background color of the footer. UIColor.white
FooterIconsColor The color of the attachment, send, and mic icons located in the footer. #161513
FooterInlineIconsColor The color of the icons (if any) inside the text input field #004C8C
GlobalActionBorderColor The border color of a global action button #161513.withAlphaComponent(0.50)
GlobalActionButtonColor The color of the global action button #0077C2
GlobalActionLabelTextColor The color of a global action label #161513
HeaderColor The background color of the header #F1EFED
HeaderIconsColor The color for the clear message, volume, and mute header icons. #161513
HeaderTextColor The text color for the connection status, typing status, and chat title header items #161513
InputFieldColor The background color of the text input field #161513
InputFieldTextColor The color of the text in the text input field #161513
IsRTL When when set to true, flips the UI to support layout for right-to-left languages such as Arabic. When set to false, the default UI layout for left-to-right languages (English, for example). false
LinkHandler Sets how the links that appear in the chat widget as part of any message payload are opened. The possible values are LinkHandlerType.browser and LinkHandlerType.webview. This behavior can be overriden for specific URL actions using the beforeDisplay() delegate by changing the action type from url to webview. LinkHandlerType.browser
PopupBackgroundColor The background color of the popup views. UIColor.white
PopupIconColor The color of the icons in popup views. #161513
PopupTextColor The text color in popup views. #161513
RatingStarColor The color of a feedback button before the user has selected it. UIColor.white
RatingStarColorFill The color of a feedback button after the user has selected it. #0077C2
SpeechVisualizationColor The color of the speech visualization bars #161513
SpeechVisualizerContainerBackground The background color of the speech visualization view UIColor.white
Theme The UI theme for the application. Valid values are BotUITheme.REDWOOD_DARK and BotUITheme.DEFAULT. For the REDWOOD_DARK theme, we recommend #201E1C. For the DEFAULT theme, it's #004C8C. Set the color of the navigation bar using the sample app. BotUITheme.DEFAULT
TimestampColor The color for the message timestamp #161513.withAlphaComponent(0.65)
UserMessageColor The background color for a user message #E4E1DD
UserTextColor The color for the text in a text user sent by the user #161513
WebViewConfig An instance of the struct WebViewConfiguration with all fields set to their default values. Sets the configuration settings for of the webview.

Icons

You can customize the following icons by setting the name of the icon image asset in the client app.
Icon Image Asset Name
Agent Avatar "agentAvatar"
Attachment Button "attachmentButton"
Skill Avatar "botAvatar"
Clear Button "clearButton"
The close button to invoke the end conversation flow "closeButton"
Download "downloadAttachmentButton"
File Icon for a file attachment "file"
Keyboard Button "keyboardButton"
Left Arrow for horizontal cards "leftArrow"
Mic Button "micButton"
Person Avatar "personAvatar"
Rating icon used for the feedback component buttons "ratingIcon"
Right Arrow for horizontal cards "rightArrow"
Send Button "sendButton"
The button to invoke the language selection popup "selectLanguageButton"
The overflow menu button when there are three or more action buttons in the header. "overflowButton"
Volume Off Button "volumeOffButton"
Volume On Button "volumeOnButton"
Zoom "imageZoomButton"

Features

Absolute and Relative Timestamps
  • Feature flag: enableTimestamp
  • Feature flag: timestampMode

You can enable absolute or relative timestamps for chat messages. Absolute timestamps display the exact time for each message. Relative timestamps display only on the latest message and express the time in terms of the seconds, days, hours, months, or years ago relative to the previous message.The precision afforded by absolute timestamps make them ideal for archival tasks, but within the limited context of a chat session, this precision detracts from the user experience because users must compare timestamps to find out the passage of time between messages. Relative timestamps allow users to track the conversation easily through terms like Just Now and A few moments ago that can be immediately understood. Relative timestamps improve the user experience in another way while also simplifying your development tasks: because relative timestamps mark the messages in terms of seconds, days, hours, months, or years ago, you don't need to convert them for timezones.

Configure Relative Timestamps

To add a relative timestamp, enableTimestamp must be enabled (true) and timestampMode, which controls the style of timestamp, must be timestampMode.relative. By setting timestampMode.relative, an absolute timestamp displays before the first message of the day as a header. This header displays when the conversation has not been cleared and older messages are still available in the history.

This timestamp is updated at following regular intervals (seconds, minutes, etc.) until a new message is received.
  • For first 10s
  • Between 10s-60s
  • Every minute between 1m-60m
  • Every hour between 1hr-24hr
  • Every day between 1d-30d
  • Every month between 1m-12m
  • Every year after first year
When a new message is loaded into the chat, the relative timestamp on the previous message is removed and a new timestamp appears on the new message displaying the time relative to the previous message. At that point, the relative timestamp updates until the next messages arrives.
Actions Layout

Use the BotsProperties.actionsLayout configuration settings to display the action buttons in horizontal or vertical layouts. The layout can be set for local actions, global actions, card actions, and form actions. The default value is horizontal for all action types.

BotsProperties.actionsLayout = ActionsLayout(local: .horizontal,global: .vertical,card: .horizontal,form: .horizontal)
Agent Avatars

For skills integrated with live agent support, the agentAvatar setting enables the display of an avatar icon for the messages sent by the agents. You configure this with the URL of the icon that displays alongside the agent messages.

Dynamically Update Avatars and Agent Details

You can enable the user and agent avatars to be dynamically updated at runtime using the setUserAvatar(avatarAsset : String), getAgentDetails(), and setUserAvatar(avatarAsset : String).

Set the User Avatar
The setPersonAvatar(avatarAsset : String) enables the dynamic updating of the user avatar at runtime. This method sets the user avatar for the all the messages, including previous messages. The avatarAsset can be:
  • The name of the asset from the project Assets folder.
  • An external link to the image source as shown in the following example.
BotsUIManager.shared().setPersonAvatar(avatarAsset: "https://picsum.photos/200/300")
BotsUIManager.shared().setPersonAvatar(avatarAsset: "userAvatarInAssetsFolder") 
Set the Agent Details

You can customize the agent details using the setAgentDetails(agentDetails: AgentDetails) API. Along with the agent name, the other attributes that you can use this API to customize are text color and the avatar. If no agent avatar has been configured, the avatar can be configured dynamically with the agent name initials. You can also customize the color of these initials and background color. The getAgentDetails() API retrieves the current agent details.

Although these APIs can be called at any time, we recommended using them with either the onReceiveMessage() or beforeDisplay() events.

setAgentDetails(agentDetails: AgentDetails)
To override the agent details received from server, use this API as follows:

Note:

All of the parameters of the AgentDetails object are optional.
// to override avatar , name and name text colorlet agentDetails = AgentDetails(name: "Bob", avatarImage: "https://picsum.photos/200/300", nameTextColor: .red)
// to override avatar , namelet agentDetails = AgentDetails(name: "Bob", avatarImage: "https://picsum.photos/200/300")
// to override avatar, name, name text color,avatar initials color , avatar background let agentDetails = AgentDetails(name: "Bob", nameTextColor: .red,avatarTextColor: .blue,avatarBackgroundColor: .green)
BotsUIManager.shared().setAgentDetails(agentDetails: agentDetails)
Additionally, each property of the AgentDetails object can be modified. For example:
let agentDetails = AgentDetails()
agentDetails.name = "Bob"
agentDetails.avatarImage = "agentAvatar"
agentDetails.nameTextColor = .red
agentDetails.avatarBackgroundColor = .green
agentDetails.avatarTextColor = .brown
BotsUIManager.shared().setAgentDetails(agentDetails: agentDetails)
getAgentDetails()
Returns an object containing the agent details.
let agentDetails = BotsUIManager.shared().getAgentDetails()
Attachment Filtering

Feature flag: shareMenuConfiguration

Use shareMenuConfiguration to restrict, or filter, the item types that are available in the share menu popup, set the file size limit in KB for uploads (such as 1024 in the following snippet), and customize the menu’s icons and labels. The default and the max limit is 25 MB.

Note:

Before you can configure shareMenuConfiguration, you must set enableAttachment to true.
botsConfiguration.shareMenuConfiguration = ([ShareMenuItem.files, ShareMenuItem.camera, ShareMenuItem.location], [ShareMenuCustomItem(types: [String(kUTTypePDF)], label: "PDF Files", maxSize: 1024), ShareMenuCustomItem(types: [String(kUTTypeText)], label: "Text Files")])
For the types, you have to use the CFString for the corresponding file type and convert it to String. Any other string will not be valid. You can allow users to upload all file types by setting the types as String(kUTTypeItem).
public func shareMenuItems(shareMenuItems: ([ShareMenuItem], [ShareMenuCustomItem]))
You can dynamically update the share menu items popup by calling the BotsManager.shared().shareMenuItems(shareMenuItems: ([ShareMenuItem], [ShareMenuCustomItem])) API.
BotsManager.shared().shareMenuItems([ShareMenuItem.files, ShareMenuItem.camera, ShareMenuItem.location], [ShareMenuCustomItem(types: [String(kUTTypePDF)], label: "PDF Files", maxSize: 1024), ShareMenuCustomItem(types: [String(kUTTypeText)], label: "Text Files")])
public func shareMenuItems() -> ([ShareMenuItem], [ShareMenuCustomItem])
You can get the share menu items list by calling the
BotsManager.shared().shareMenuItems();
API.
BotsManager.shared().shareMenuItems()
Connect, Disconnect, and Destroy Methods

The skill can be connected or disconnected, or the SDK can be destroyed, using the public func destroy(), public func disconnect(), and the public func connect() methods.

public func destroy()

Destroys the SDK by closing any active connection, voice recognition, speech synthesis, file uploads, and by removing the SDK view controller. Once called, none of the public API methods can be called. They will only be active again after the initialize(botsConfiguration: BotsConfiguration, completionHandler: @escaping (ConnectionStatus, Error?) -> ()) method is called again to initialize the SDK.

public func disconnect()
All network connections are closed after calling the disconnect method.
BotsManager.shared().disconnect()
public func connect()
The web socket connection is established if the skill was in a disconnected state.
BotsManager.shared().connect()
public func connect(botsConfiguration: BotsConfiguration)
When this method is called with a new BotsConfiguration, the existing web socket connection is closed, and a new connection is established using the new channel properties. Other properties set in BotsConfiguration remain as is.
var botsConfiguration = BotsConfiguration(url: url, userId: userId, channelId: channelId)
BotsManager.shared().connect(botsConfiguration: botsConfiguration)
Default Client Responses

Feature flag: enableDefaultClientResponse

Use enableDefaultClientResponse: true to provide default client-side responses accompanied by a typing indicator when the skill response has been delayed, or when there's no skill response at all. If the user sends out the first message/query, but the skill does not respond with the number of seconds set by defaultGreetingTimeout, the skill can display a greeting message that's configured using the odais_default_greeting_message translation string. Next, the client checks again for the skill's response. The client displays the skill's response if it has been received, but if it hasn't, then the client displays a wait message (configured with the odais_default_wait_message translation string) at intervals set by the defaultWaitMessageInterval flag. When the wait for the skill response exceeds the threshold set by the typingStatusTimeout flag, the client displays a sorry response to the user and stops the typing indicator. You can configure the sorry response using the odais_default_sorry_message translation string.

Delegation
The delegation feature lets you set a delegate to receive callbacks before certain events in the conversation. To set a delegate, a class must conform to the BotsMessageServiceDelegate protocol and implement the following methods:
public func beforeDisplay(message: [String: Any]?) -> [String: Any]?

This method allows a skill’s message payload to be modified before it is displayed in the conversation. The message payload returned by the method is used to display the message. If it returns nil, then the message is not displayed.

public func beforeSend(message: [String: Any]?) -> [String: Any]?

This method allows a user message payload to be modified before it is sent to the chat server. The message payload returned by the method is sent to the skill. If it returns nil, then the message is not sent.

public func beforeSendPostback(action: [String: Any]?) -> [String: Any]?
The public func beforeSendPostback(action: [String: Any]?) -> [String: Any]? allows a postback action payload to be modified before it is sent to the chat server. The action payload returned by the method is sent to the skill. If it returns nil, then the postback action selected by the user is not sent to the chat server.
public class ViewController: UIViewController, BotsMessageServiceDelegate {
    func beforeSend(message: [String : Any]?) -> [String : Any]? {
        // Handle before send delegate here
    }
    
    func beforeDisplay(message: [String : Any]?) -> [String : Any]? {
        // Handle before display delegate here
    }
    
    func beforeSendPostback(action: [String : Any]?) -> [String : Any]? {
        // Handle before send postback action delegate here
    }
}
The instance, which conforms to the BotsMessageServiceDelegate protocol, should be assigned to the BotsManager.shared().delegate property as shown in the following code snippet for initializing the SDK:
BotsManager.shared().delegate = self
End the Chat Session

Feature flag: enableEndConversation

enableEndConversation, when set to true, adds a close button to the header view that enables users to explicitly end the current chat session. A confirmation prompt dialog opens when users click this close button and when they confirm the close action, the SDK sends an event message to the skill that marks the end of the chat session. The SDK then disconnects the skill from the instance, collapses the chat widget, and erases the current user's conversation history. The SDK also raises a chatend event in the BotsEventListener protocol that you can implement.

Opening the chat widget afterward starts a new chat session.

Tip:

The conversation can also be ended by calling BotsManager.shared().endChat() method, which you can use when the SDK is initialized in the headless mode.

Headless SDK

The SDK can be used without its UI. The SDK maintains the connection to server and provides APIs to send messages, receive messages, and get updates for the network status and for other services. You can use the APIs to interact with the SDK and update the UI.

You can send a message using any of the send() APIs available in BotsManager class. For example, public func send(message: UserMessage) sends text message to skill or digital assistant.

public func send(message: UserMessage)

This function sends a message to the skill. Its message parameter is an instance of a class which conforms to the UserMessage class. In this case, it is UserTextMessage.BotsManager.shared().send(message: UserTextMessage(text: "I want to order a pizza", type: .text))

BotsEventListener
To listen for the connection status change, a message received from skill and attachment upload status events, a class can implement the BotsEventListener protocol which then implements the following methods:
  • onStatusChange(ConnectionStatus connectionStatus) – This method is called when the WebSocket connection status changes. Its connectionStatus parameter is the current status of the connection. Refer to the API docs included in the SDK for more details about the ConnectionStatus enum.
  • onReceiveMessage(message: BotsMessage) – This method is called when a new message is received from the skill. Its message parameter is the message received from the skill. Refer to the API docs included in the SDK for more details about the BotsMessage class.
  • onUploadAttachment(message: BotsAttachmentMessage) – This method is called when an attachment upload has completed. Its message parameter is the BotsAttachmentMessage object for the uploaded attachment.
  • onDestroy() – This method is called when the destroy() method is called.
  • onInitialize() – This method is called when the initialize(botsConfiguration: BotsConfiguration, completionHandler: @escaping (ConnectionStatus, Error?) -> ()) method is called. It takes the following parameter:
    • newLanguage – The SupportedLanguage object for the newly set chat language.
  • beforeEndConversation() – This method is called when the end conversation session is initiated.
  • chatEnd() – A callback method triggered after conversation has ended successfully.
extension ViewController: BotsEventListener {
    func onReceiveMessage(message: BotsMessage) {
        // Handle the messages received from skill or Digital Assistant
    }

    func onUploadAttachment(message: BotsAttachmentMessage) {
        // Handle the post attachment upload actions
    }

    func onStatusChange(connectionStatus: ConnectionStatus) {
        // Handle the connection status change
    }

    func onInitialize() {
        //Handle initialization
    }

    func onDestroy() {
        //Handle destroy
    }

    func onChatLanguageChange(newLanguage: SupportedLanguage) {
        //Handle the language change.
    }

    func beforeEndConversation(completionHandler: @escaping (EndConversationStatus) -> Void) {
        //Do the desired cleanup before session is closed.
        return completionHandler(.success) // if cleanup was successfull.
        return completionHandler(.success) // if there was en error cleaning up.
    }
    
     func chatEnd() {
        //Handle successfull session end from server before the SDK is destroyed.
     }
}
The instance which conforms to the BotsEventListener protocol should be assigned to the BotsManager.shared().botsEventListener property as illustrated in the following code snippet for initializing the SDK:
BotsManager.shared().botsEventListener = self
In-Widget Webview

UI Property: LinkHandler

You can configure the link behavior in chat messages to allow users to access web pages from within the chat widget. Instead of having to switch from the conversation to view a page in a tab or separate browser window, a user can remain in the chat because the chat widget opens the link within a webview.

Configure the In-Widget Webview

UI Property: WebViewConfig

You can set the webview configuration by setting the LinkHandler property to LinkHandlerType.webview. WebViewConfig can be set to a WebViewConfiguration struct instance.
BotsProperties.LinkHandler = LinkHandlerType.webview
//Set the properties which you want changed from the default values.
BotsProperties.WebViewConfig.webViewSize = WebViewSize.full
BotsProperties.WebViewConfig.clearButtonLabelColor = UIColor.black
As illustrated in this code snippet, you can set the following attributes for the webview.
Attribute Settings
webViewSize Sets the screen size of the in-widget webview window with WebviewSize attribute, which has two values: parial (WebviewSize.partial) and full (WebviewSizeWindow.full).
clearButtonLabel Sets the text used for clear/close button in the top right corner of webview. The default text is taken from the string set to odais_done in the Localizable.strings file.
clearButtonIcon Sets an icon for the clear button, which appears left-aligned inside the button. By default, there's no icon set for the clear button. It's an empty string.
clearButtonLabelColor Sets the color of text of clear button label. The default color is UIColor.white.
clearButtonColor Sets the background color for the clear button. The default color is UIColor.clear.
webviewHeaderColor Sets the background color for webview header.
webviewTitleColor Sets the color of title in the header. The title is the URL of the web link that has been opened.
Message Timestamp Formatting

The timestampFormat flag formats timestamps that display in the messages. It can accept a string consisting of format tokens like "hh:mm:ss" and other formats supported by the Swift DateFormatter.

Multi-Lingual Chat

Feature flag: multiLangChat

The iOS SDK's native language enables the chat widget to detect a user's language or allow users to select the conversation language. Users can switch between languages, but only in between conversations, not during a conversation because the conversation gets reset whenever a user selects a new language.

Enable the Language Menu
You can enable a menu that allows users to select a preferred language from a dropdown menu by defining the multiLangChat property with an object containing the supportedLanguage array, which is comprised of language tags (lang) and optional display labels (label). Outside of this array, you can optionally set the default language with the primaryLanguage attribute (primaryLanguage: "en" in the following snippet)..
botsConfiguration.multiLangChat = MultiLangChat(supportedLanguages: [SupportedLanguage(lang: "en", label: "English"), SupportedLanguage(lang: "fr", label: "French"), SupportedLanguage(lang: "es", label: "Spanish")], primaryLanguage: "en")
The chat widget displays the passed-in supported languages in a dropdown menu that's located in the header. In addition to the available languages, the menu also includes a Detect Language option. When a user selects a language from this menu, the current conversation is reset, and a new conversation is started with the selected language. The language selected by the user persists across sessions in the same browser, so the user's previous language is automatically selected when the user revisits the skill through the page containing the chat widget.
Here are some things to keep in mind when configuring multi-language support:
  • You need to define a minimum of two languages to enable the dropdown menu to display.
  • If you omit the primaryLanguage attribute, the widget automatically detects the language in the user profile and selects the Detect Language option in the menu.
  • The label key is optional for the natively supported languages: fr displays as French in the menu, es displays as Spanish, and so on.
  • While label is optional, if you've added a language that's not one of the natively supported languages, then you should add a label to identify the tag. For example, if you don't define label: 'हिंदी', for the lang: "hi", then the dropdown menu displays hi instead, contributing to a suboptimal user experience.
Disable Language Menu

Starting with Version 21.12, you can also configure and update the chat language without also having to configure the language selection dropdown menu by passing MultiLangChat(primaryLanguage: String).

Language Detection

In addition to the passed-in languages, the chat widget displays a Detect Language option in the dropdown menu. Selecting this option tells the skill to automatically detect the conversation language from the user's message and, when possible, to respond in the same language.

You can dynamically update the selected language by calling the BotsManager.shared().setPrimaryLanguage(primaryLanguage: String) API. If the passed lang matches one of the supported languages, then that language is selected. When no match can be found, Detect Language is activated. You can also activate the Detected Language option by calling BotsManager.shared().setPrimaryLanguage(primaryLanguage: "und") API, where "und" indicates undetermined or by passing primaryLanguage:nil.

You can update the chat language dynamically using the setPrimaryLanguage(primaryLanguage: String) API even when the dropdown menu has not been configured.

Multi-Lingual Chat Quick Reference
To do this... ...Do this
Display the language selection dropdown menu to end users. Pass MultiLangChat(supportedLanguages: [SupportedLanguage]).
Set the chat language without displaying the language selection dropdown menu to end users. Pass MultiLangChat(primaryLanguage: String).
Set a default language. Pass MultiLangChat(supportedLanguages: [SupportedLanguage], primaryLanguage: String).
Enable language detection. Pass primaryLanguage:nil or primaryLanguage:"und".
Dynamically update the chat language. Call the setPrimaryLanguage(primaryLanguage: String) API.
Share Menu Options
By default, the share menu displays options for the following file types:
  • visual media files (images and videos)
  • audio files
  • general files like documents, PDFs, and spreadsheets
  • location
The sharePopupConfiguration setting allows you to restrict the items that display in the share menu. By passing a tuple of arrays to ShareMenuConfiguration -- shareMenuConfiguration = ([ShareMenuItem], [ShareMenuCustomItem]) -- you can restrict, or filter, the type of items that are available in the menu, customize the menu's icons and labels, and limit the upload file size. The tuple is has an array of share menu options of type ShareMenuItem and an array of share menu options of type ShareMenuCustomItem. Pass either as an empty array for all file types.
public func shareMenuItems(shareMenuItems: ([ShareMenuItem], [ShareMenuCustomItem]))
You can enable dynamic updating of the menu using the
shareMenuItems(shareMenuItems: ([ShareMenuItem], [ShareMenuCustomItem]))
method.
public func shareMenuItems() -> ([ShareMenuItem], [ShareMenuCustomItem])

This method returns the existing configuration of share menu items.

Speech Recognition
  • Feature flag: enableSpeechRecognition
  • Functionality configuration: enableAutoSendSpeechResponse

Setting the enableSpeechRecognition feature flag to true enables the microphone button to display in place of the send button whenever the user input field is empty. The speech is converted to text and sent to the skill or digital assistant. If the speech is partially recognized, then the partial result is displayed in a popup that's opened by clicking the microphone button.

Setting this property to true also supports the functionality enabled by the enableAutoSendSpeechResponse property, which when also set to true, enables the user's speech response to be sent to the chat server automatically while displaying the response as a sent message in the chat window. You can allow users to first edit (or delete) their dictated messages before they send them manually by setting enableSpeechRecognitionAutoSend to false.

Speech recognition is utilized through the following methods:
public func startRecording()

Starts recording the user's voice message.

public func stopRecording()

Stops recording the user's message.

public func isRecording() -> Bool

Checks whether the voice recording has started or not. Returns true if the recording has started. Otherwise, it returns false.

The onSpeechResponseReceived(data: String, final: Bool) function from the BotsEventListener protocol can be used to handle all the responses from the speech server.
BotsManager.shared().startRecording()
if (BotsManager.shared().isRecording()) {
    BotsManager.shared().stopRecording() // Stop voice recording
}
Speech Synthesis
  • Feature flag: enableSpeechSynthesis
  • Functionality configuration: speechSynthesisVoicePreferences
The SDK has been integrated with speech synthesis to read the skill's message aloud when a new message is received from skill.
  • You enable this feature by setting the enableSpeechSynthesis feature flag to true.
  • You can set the preferred language that read the skill's messages aloud with the speechSynthesisVoicePreferences property. This property enables a fallback when the device doesn't support the preferred language or voice. If the device does not support the preferred voice, then the default voice for the preferred language is used instead. When neither the preferred voice or language are supported, then the default voice and language are used.
public func speak(text: String)
Starts reading the skill's response aloud. Its text parameter is the text for the skill's message that's read aloud.
BotsManager.shared().speak(text: "What kind of crust do you want?")
public func stopSpeech()
Stops reading the skill's response aloud.
BotsManager.shared().stopSpeech()
Speech Service Injection

Feature flag: ttsService

The ttsService feature flag allows you to inject any text-to-speech (TTS) service -- your own, or one provided by a third-party vendor -- into the SDK. To inject a TTS service, you must first set the enableSpeechSynthesis feature flag to true and then pass an instance of the TTSService interface to the ttsService flag.

The TTSService Protocol
You create an instance of a class that's an implementation of the TTSService interface. It implements the following methods:
  • speak(text: String) - This method adds the text that's to be spoken to the utterance queue. Its text parameter is the text to be spoken.
  • isSpeaking() - This method checks whether or not the audio response is being spoken. It returns false if no audio response is being spoken.
  • stopSpeech() - This method stops any ongoing speech synthesis.
   class CustomTTSService: TTSService {

        func speak(text: String) {
            // Adds text to the utterance queue to be spoken
        }
        
        func stopSpeech() {
            // Stops any ongoing speech synthesis
        }
        
        func isSpeaking() -> Bool {
            // Checks whether the bot audio response is being spoken or not.
        }
    }
Typing Indicator for User-Agent Conversations

Feature flag: enableSendTypingStatus

When this flag is enabled, the SDK sends a RESPONDING typing event along with the text that's currently being typed by the user to Oracle Fusion Cloud B2C Service (Oracle B2C Service). This shows a typing indicator on the agent console. When the user has finished typing, the SDK sends a LISTENING event to Oracle B2C Service. This hides the typing indicator on the agent console.

Similarly, when the agent is typing, the SDK receives a RESPONDING event from Oracle B2C Service. On receiving this event, the SDK shows a typing indicator to the user. When the agent is idle, the SDK receives LISTENING event from Oracle B2C Service. On receiving this event, the SDK hides the typing indicator that's shown to the user.

The sendUserTypingStatus API enables the same behavior for headless mode.
 public func sendUserTypingStatus(status: TypingStatus, text: String? = nil)
  • To show the typing indicator on the agent console:
    BotsManager.shared().sendUserTypingStatus(status: .RESPONDING, text: textToSend)
  • To hide the typing indicator on the agent console:
    BotsManager.shared().sendUserTypingStatus(status: .LISTENING)
  • To control user-side typing indicator, use the onReceiveMessage() event. For example:
        public func onReceiveMessage(message: BotsMessage) {
            if message is AgentStatusMessage {
                if let status = message.payload["status"] as? String {
                    switch status {
                    case TypingStatus.LISTENING.rawValue:
                        hideTypingIndicator()
                    case TypingStatus.RESPONDING.rawValue:
                        showTypingIndicator()
                    }
                }
            }
        }
There are two more settings in BotsConfiguration that provide additional control:
  • typingStatusInterval – By default, the SDK sends the RESPONDING typing event every three seconds to Oracle B2C Service. Use this flag to throttle this event. The minimum value that can be set is three seconds.
  • enableAgentSneakPreview - Oracle B2C Service supports showing the user text as it's being entered. If this flag is set to true (the default is false), then the SDK sends the actual text. To protect user privacy, the SDK sends instead of the text to Oracle B2C Service when the flag is set to false.

    Note:

    This feature must be enabled in both the SDK and the Oracle B2C Service chat configuration.
Voice Visualizer

When voice support is enabled (botsConfiguration.enableSpeechRecognition = true), the footer of the chat widget displays a voice visualizer, a dynamic visualizer graph that indicates the frequency level of the voice input. The visualizer responds to the modulation of the user's voice by indicating whether the user is speaking too softly or too loudly. This visualizer is created using Swift's AVAudioEngine which is exposed in the onAudioReceived method in the SpeechEventListener protocol for use in headless mode.

The chat widget displays a voice visualizer when users click the voice icon. It's an indicator of whether the audio level is sufficiently high enough for the SDK to capture the user’s voice. The user’s message, as it is recognized as text, displays below the visualizer.

Note:

Voice mode is indicated when the keyboard icon appears.

When botsConfiguration.enableSpeechAutoSendSpeechResponse = true, the recognized text is automatically sent to the skill after the user has finished dictating the message. The mode then reverts to text input. When botsConfiguration.enableSpeechAutoSendSpeechResponse = false, the mode also reverts to text input, but in this case, users can modify the recognized text before sending the message to the skill.

Message Model

To use features like headless mode and delegate, you need to understand both user and skill messages. Everything that's received or sent from the Oracle Chat Server is represented as a message, one that's sent from the user to the skill, or from the skill to the user.

Base Types
These are the base types used in all messages sent from the user to the skill and vice versa. They are the building blocks of all messages.
Attachment
Represents an attachment that's sent by the user.
Name Description Type Required?
type The attachment type string (valid values: audio, file, image, video) Yes
url The download URL for the attachment string Yes
For example:
{
    "type": "image",
    "url": "https://www.oracle.com/us/assets/hp07-oow17-promo-02-3737849.jpg"
}
Location
Represents a location object.
Name Description Type Required?
title The location title string No
URL The URL for displaying the location on a map string No
latitude The GPS coordinate's longitude value double Yes
longitude The GPS coordinate's latitude value double Yes
For example:
{
    "title": "Oracle Headquarters",
    "url": "https://www.google.com.au/maps/place/37°31'47.3%22N+122°15'57.6%22W",
    "longitude": -122.265987,
    "latitude": 37.529818
}
Action
An action represents something that the user can select.
Name Description Type Required?
type The action type string Yes
label The descriptive label text for the action. string At least one label or imageUrl must be present.
imageUrl The image for the action string At least one label or imageUrl must be present.
PostbackAction
Sends a predefined postback back to the skill when the user selects an action.
Name Description Type Required?
type The action type "postback" Yes
postback The postback that's returned when the user selects an action. A string or JSON object Yes
For example:
{
    "type": "postback",
    "label": "Large Pizza",
    "imageUrl": "https://example.com/images/gallery/locations/11.jpg",
    "postback": {
        "state": "askSize",
        "action": "getCrust"
    }
}
CallAction
Requests the client to call a specified phone number on behalf of the user.
Name Description Type Required?
type The action type "call" Yes
phoneNumber The phone number to call string Yes
For example:
{
    "type": "call",
    "label": "Call Support",
    "imageUrl": "http://example.com.ar/files/2016/05/cuidado.jpg",
    "phoneNumber": "18005555555"
}
urlAction

Requests the client to open a website in a new tab or in an in-app browser.

Name Description Type Required?
type The action type "call" Yes
URL The URL of the website that's displayed. string Yes
For example:
{
    "type": "url",
    "label": "Open URL",
    "imageUrl": "http://example.com.ar/files/2016/05/cuidado.jpg",
    "url": "https://example.com/images/gallery/locations/11.jpg",
}
LocationAction
Requests the client to ask for the user's location.
Name Description Type Required?
type The action type "location" Yes
For example:
{
    "type": "location",
    "label": "Share location",
    "imageUrl": "http://images.example.com/location-clipart-location-pin-clipart-1.jpg"
}
Card
Represents a single card in the message payload.
Name Description Type Required?
title The title of the card, displayed as the first line on the card. string Yes
description The description of the card string No
imageUrl The URL of the image that is displayed. string No
URL The website URL that's opened by a tap. string No
actions An array of actions related to the text array No
channelExtensions The channel-specific extension properties associated with the message A JSON object No
Heading
Represents a heading for tables in a Table or Table-Form object.
Name Description Type Required?
label The heading label String Yes
alignment The positioning of ht e label within the cell "left", "right", "center" Yes
width The suggested percentage of the table width that should be provided to the heading.   No
channelExtensions The channel-specific extension properties associated with the message A JSON object No
Row
Represents an array of fields.
Name Description Type Required?
fields An array of fields Array <field> Yes
channelExtensions The channel-specific extension properties associated with the message A JSON object No
Field
Represents the atomic information of a table cell or a form field within the Table, Form, and Table-Form objects, provided as key-value pair.
Name Description Type Required?
displayType The field type "text", "link" Yes
label The field key String Yes
value The field value String No
linkLabel A short label for the link value if displayType is link. String No
alignment The positioning of the label within its cell "left", "right", "center" No
width The suggested percentage of the table width that should be provided to the field   No
channelExtensions The channel-specific extension properties associated with the message A JSON object No
Form
Represents an array of fields along with a title. Used in Table-Form messages for nested forms of a table row.
Name Description Type Required?
title The form title String No
field An array of fields Array <field> Yes
actions An array of actions Array <BotsAction> No
channelExtensions The channel-specific extension properties associated with the message JSON object No
PaginationInfo

Represents the paging information for the results in the Table, Form, and Table-Form objects.

Name Description Type Required?
totalCount The total results count number Yes
rangeSize The range size of the results per page number Yes
status The paging status message string Yes
currentRangeSize The size of curent range of results number Yes
rangeStart The starting offset of the current range of results number Yes
nextRangeSize The size of the next range of results number Yes
hasPrevious Indicates whether there is a previous set of results boolean Yes
hasNext Indicates whether there is a next set of results boolean Yes
Conversation Message
All of the messages that are part of a conversation have the following structure:
Name Description Type Required?
messagePayload The message payload Message Yes
userId The user ID string Yes
For example:
{
    "messagePayload": {
        "text": "show menu",
        "type": "text"
    },
    "userId": "guest"
}
User Message

Represents a message sent from the user to the skill.

User Text Message
The simple text message that's sent to the server.
Name Description Type Required?
type The message type "text" Yes
text The message text string Yes
For example:
{
    "messagePayload": {
        "text": "Order Pizza",
        "type": "text"
    },
    "userId": "guest"
}
User Postback Message
The postback response message that's sent to the server.
Name Description Type Required?
type The message type "postback" Yes
text The postback text string No
postback The postback of the selected action A string or JSON object Yes
For example:
{
    "messagePayload": {
        "postback": {
            "variables": {
                "pizza": "Small"
            },
            "system.botId": "69BBBBB-35BB-4BB-82BB-BBBB88B21",
            "system.state": "orderPizza"
        },
        "text": "Small",
        "type": "postback"
    },
    "userId": "guest"
}
User Attachment Message
The attachment response message that's sent to the server.
Name Description Type Required?
type The message type "attachment" Yes
attachment The attachment metadata Attachment Yes
For example:
{
    "messagePayload": {
        "attachment": {
            "type": "image",
            "url": "http://oda-instance.com/attachment/v1/attachments/d43fd051-02cf-4c62-a422-313979eb9d55"
        },
        "type": "attachment"
    },
    "userId": "guest"
}
User Location Message
The location response message that's sent to the server.
Name Description Type Required?
type The message type "location" Yes
location The user location information Location Yes
For example:
{
    "messagePayload": {
        "location": {
            "latitude": 45.9285271,
            "longitude": 132.6101925
        },
        "type": "location"
    },
    "userId": "guest"
}
Skill Message

Represents the message sent from the skill to the user.

Message
Message is an abstract base type for all other messages. All messages extend it to provide some information.
Name Description Type Required?
type The message type string Yes
Skill Text Message
Represents a text message.
Name Description Type Required
type The message type "text" Yes
text The message text string Yes
headerText The header text for cards string No
footerText The footer text for cards string No
actions An array of actions related to the text. array No
globalActions An array of global actions related to the text. array No
channelExtensions The channel-specific extension properties associated with the message. "displayType" : "stars" identifies the feedback component. JSON object No
For example:
{
    "messagePayload": {
        "type": "text",
        "text": "What do you want to do?",
        "actions": [
            {
                "type": "postback",
                "label": "Order Pizza",
                "postback": {
                    "state": "askAction",
                    "action": "orderPizza"
                }
            },
            {
                "type": "postback",
                "label": "Cancel A Previous Order",
                "postback": {
                    "state": "askAction",
                    "action": "cancelOrder"
                }
            }
        ]
        ],
          "channelExtensions": {
             "displayType":"stars"
          }
    },
    "userId": "guest"
    "userId": "guest",
    "msgId": "message_id",
    "source": "BOT"
}
Skill Attachment Message
Represents an attachment message.
Name Description Type Required
type The message type "attachment" Yes
attachment The attachment sent Attachment Yes
headerText The card's header text string No
footerText the card's footer text string No
actions An array of actions related to the text. array No
globalActions An array of global actions related to the text. array No
channelExtensions The channel-specific extension properties associated with the message JSON object No
Skill Card Message
Represents a set of choices that are displayed for the user, either horizontally as carousels or vertically as lists.
Name Description Type Required
type The message type "card" Yes
layout Whether to display the messages horizontally or vertically. string (values: horizontal, vertical) Yes
cards An array of cards to be rendered. array Yes
headerText The cards' header text string No
actions An array of actions related to the text. array No
globalActions An array of global actions related to the text. array No
channelExtensions The channel-specific extension properties associated with the message A JSON object No
{
    "messagePayload": {
        "type": "card",
        "layout": "horizontal",
        "cards": [
            {
                "title": "Hawaiian Pizza",
                "description": "Ham and pineapple on thin crust",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Order Small",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "hawaiian",
                                "pizzaCrust": "thin",
                                "pizzaSize": "small"
                            }
                        }
                    },
                    {
                        "type": "postback",
                        "label": "Order Large",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "hawaiian",
                                "pizzaCrust": "thin",
                                "pizzaSize": "large"
                            }
                        }
                    }
                ]
            },
            {
                "title": "Cheese Pizza",
                "description": "Cheese pizza (i.e. pizza with NO toppings) on thick crust",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Order Small",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "cheese",
                                "pizzaCrust": "thick",
                                "pizzaSize": "small"
                            }
                        }
                    },
                    {
                        "type": "postback",
                        "label": "Order Large",
                        "postback": {
                            "state": "GetOrder",
                            "variables": {
                                "pizzaType": "cheese",
                                "pizzaCrust": "thick",
                                "pizzaSize": "large"
                            }
                        }
                    }
                ]
            }
        ],
        "globalActions": [
            {
                "type": "call",
                "label": "Call for Help",
                "phoneNumber": "123456789"
            }
        ]
    },
    "userId": "guest"
}
Skill Table Message
Represents a message that returns the results of a query in table form The message consists of an array of headings and an array of rows. The rows themselves contain a fields array that represents individual cells.

Note:

This message type is used for SQL dialogs.
Name Description Type Required?
type The message type "table" Yes
headings An array of table headings Array<Heading> Yes
rows An array of table rows. Each row contains a fields array that represents the table cells. Array<Row> Yes
paginationInfo The paging information for the results in the table PaginationInfo No
actions An array of actions related to the table Array<Action> No
globalActions An array of global actions Array<Action> No
channelExtensions The channel-specific extension properties associated with the message A JSON object No
{
    "type":"table",
    "headerText":"A-Team",
    "headings":[
        {
            "width":20,
            "label":"First Name",
            "alignment":"left"
        },
        {
            "width":20,
            "label":"Last Name",
            "alignment":"left"
        },
        {
            "width":35,
            "label":"Title",
            "alignment":"left"
        },
        {
            "width":25,
            "label":"Phone",
            "alignment":"right"
        }
    ],
    "rows":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"David"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Davidson"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Machine Learning Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "width":20,
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Eric"
                },
                {
                    "displayType":"text",
                    "width":20,
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Eastman Junior"
                },
                {
                    "displayType":"text",
                    "width":35,
                    "label":"Title",
                    "alignment":"left",
                    "value":"Docker Expert"
                },
                {
                    "displayType":"text",
                    "width":25,
                    "label":"Phone",
                    "alignment":"right",
                    "value":"1234567890"
                }
            ]
        }
    ],
    "paginationInfo":{
        "currentRangeSize":5,
        "rangeStart":0,
        "nextRangeSize":-3,
        "hasPrevious":false,
        "hasNext":false,
        "totalCount":5,
        "rangeSize":8,
        "status":"Showing 1-5 of 5 items"
    }
}
Skill Form Message
Represents a message that returns the results of a query in a form that's read only. The message consists of an array of form results. Each form result contains a fields array with key-value pairs that represent a field.

Note:

This message type is used for SQL dialogs.
Name Description Type Required?
type The message type "form" Yes
forms An array of form results. Each result contains a fields array that represents the form fields. Array<Row> Yes
formColumns A number suggesting the number of columns in which the fields of the form should be grouped. 1, 2 Yes
paginationInfo The paging information for the results in the form PaginationInfo No
actions An array of actions related to the form Array<Action> No
globalActions An array of global actions Array<Action> No
channelExtensions The channel-specific extension properties associated with the message A JSON object No
{
    "type":"form",
    "headerText":"A-Team",
    "forms":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/aaron-adams-4862752"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Bobbrown"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Bob is a member of the cloud architects team which is specialized in enterprise mobility and cloud development. Bob has been directly involved with Oracle middleware since 2005 during which he held different roles in managing highly specialized teams."
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                },
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Charlie-chase-97a418"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Charlie is a member of the enterprise mobility team. Charlie has 20+ years experience with custom development. Charlie is an expert on mobile cloud services and development tools. He is the creator of productivity tools. His latest passion is building chatbots with a minimum amount of custom code."
                }
            ]
        }
    ],
    "formColumns":2,
    "paginationInfo":{
        "currentRangeSize":3,
        "rangeStart":0,
        "nextRangeSize":2,
        "hasPrevious":false,
        "hasNext":true,
        "totalCount":5,
        "rangeSize":3,
        "status":"Showing 1-3 of 5 items"
    },
    "globalActions":[
        {
            "postback":{
                "variables":{},
                "action":"system.showMore"
            },
            "label":"Show More",
            "type":"postback"
        }
    ]
}
Skill Table-Form Message
This message combines the Table and Form message types. It represents a message that returns the results of a query in the form of a table. Each each row of the table has a read-only form in addition to the row information.

Note:

This message type is used for SQL dialogs.
Name Description Type Required?
type The message type "tableForm" Yes
headings An array of table headings Array<Heading> Yes
rows An array of table rows. Each row contains an array of fields that represent the table cells. Array<Row> Yes
forms An array of form results that correspond to each table row. Each form contains a fields array that represents the form fields. Array<Form> Yes
formColumns The number suggesting the number of columns in which the fields of the form should be grouped. 1, 2 Yes
paginationInfo An array of global actions related to the text Array<Action> No
actions An array of actions related to the table form Array<Action> No
globalActions An array of global actions Array<Action> No
channelExtensions The channel-specific extension properties associated with the message A JSON Object No
{
    "type":"tableForm",
    "headerText":"A-Team",
    "headings":[
        {
            "width":47,
            "label":"First Name",
            "alignment":"left"
        },
        {
            "width":47,
            "label":"Last Name",
            "alignment":"left"
        }
    ],
    "rows":[
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Aaron"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Adams"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Bob"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Brown"
                }
            ]
        },
        {
            "fields":[
                {
                    "displayType":"text",
                    "label":"First Name",
                    "alignment":"left",
                    "value":"Charlie"
                },
                {
                    "displayType":"text",
                    "label":"Last Name",
                    "alignment":"left",
                    "value":"Chase"
                }
            ]
        }
    ],
    "forms":[
        {
            "title":"View details Aaron Adams",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Demo Builder"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Aaron-adams-4862572"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left"
                }
            ]
        },
        {
            "title":"View details Bob Brown",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Multi-lingual Expert"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Bobbrown"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Bob is a member of the cloud architects team which is specialized in enterprise mobility and cloud development. Bob has been directly involved with Oracle middleware since 2005 during which he held different roles in managing highly specialized teams."
                }
            ]
        },
        {
            "title":"View details Charlie Chase",
            "fields":[
                {
                    "displayType":"text",
                    "label":"Title",
                    "alignment":"left",
                    "value":"Flow Builder Fanatic"
                },
                {
                    "displayType":"text",
                    "label":"Phone",
                    "alignment":"left",
                    "value":"1234567890"
                },
                {
                    "linkLabel":"Open Link",
                    "displayType":"link",
                    "label":"Contact",
                    "alignment":"left",
                    "value":"https://www.example.com/in/Charlie-chase-97a418"
                },
                {
                    "displayType":"text",
                    "label":"Bio",
                    "alignment":"left",
                    "value":"Charlie is a member of the enterprise mobility team. Charlie has 20+ years experience with custom development. Charlie is an expert on mobile cloud services and development tools. He is the creator of productivity tools. His latest passion is building chatbots with a minimum amount of custom code."
                }
            ]
        }
    ],
    "formColumns":2,
    "paginationInfo":{
        "currentRangeSize":3,
        "rangeStart":0,
        "nextRangeSize":2,
        "hasPrevious":false,
        "hasNext":true,
        "totalCount":5,
        "rangeSize":3,
        "status":"Showing 1-3 of 5 items"
    },
    "actions":[
        {
            "postback":{
                "variables":{

                },
                "action":"system.showMore"
            },
            "label":"Show More",
            "type":"postback"
        }
    ],
    "footerText":"Tap on a row to see personal details"
}
Skill Raw Message
Used when a component creates the channel-specific payload itself.
Name Description Type Required?
type The message type "raw" Yes
payload The channel-specific payload A JSON object Yes
channelExtensions The channel-specific extension properties associated with the message A JSON object No

Oracle iOS Channel Extensions

For Oracle iOS channels, you can extend the functionality of Common Response components with capabilities that are specific to the Oracle iOS SDK.

You access the extensions by using the channelCustomProperties element in Common Response components and setting the appropriate properties. The code has the following format:

...
            channelCustomProperties:
            - channel: "iossdk"
              properties:
                PROPERTY_NAME: "PROPERTY_VALUE"
...

You can apply channelCustomProperties in the component's metadata at the level of globalActions, responseItems, and elements of responseItems, depending on the given property.

Here are the available custom properties for Oracle iOS channels:

Name Allowed Values Applies To... Description
mediaType
  • A valid media type
  • Response items with the following attributes:
    • type: "attachment"
    • attachmentType: "file"or attachmentType: "image"
  • Cards with imageUrl specified
The media type of the attachment. For example, image/jpeg. If not specified, the media type will be resolved from the attachment URL.

For more information on using channelCustomProperties, see Channel-Specific Extensions.