Brand Messenger iOS SDK Conversation
Understand how you can initiate or launch a chat with an agent in iOS
Before we begin, make sure you have added all of the permissions as mentioned in the Add Permissions section of our Installation guide.
Initiating a chat
Implement the following code at the event or Button action designated to the conversation screen. This will launch the Chat screen.
BrandMessengerManager.show(self)
[BrandMessengerManager show:self];
If the environment is also configured with Welcome-Messages, the following can be used instead of `show(self). This will also send an API request to give the user a welcome-message.
BrandMessengerManager.showWithWelcome(vc:UIViewController?)
To just send the welcome-message API request without displaying the conversation screen, use the following
BrandMessengerManager.sendWelcomeMessageRequest { response, error in }
Intercepting Message Actions from SDK Conversation Screen
Message actions from the build-in KBMConversationViewController, such as tapping on link-buttons, can be intercepted by setting a KBMConversationViewControllerDelegate and handled outside of the SDK.
BrandMessengerManager.setMessageActionDelegate(self)
...
// Return false to let SDK handle action. Return true to handle it here.
func handleMessageAction(index: Int?, title: String?, message: KBMMessageViewModel?, cardTemplate: CardTemplate?, listAction: ListTemplate.Action?, isButtonDisabled: Bool?) -> Bool {
// There are many types of rich messages, which can return an action type 'link' to open URL.
// Below is an example to parse cardTemplate (either in single card, or card-carousel) and link-button for URLs.
if let message = message {
if message.messageType == .cardTemplate {
if let index = index, let selectedButton = cardTemplate?.buttons?[index] {
if selectedButton.action?.type == "link" {
let url = selectedButton.action?.payload?.url
print("URL on CardTemplate: \(url)")
return true
}
}
}
if message.messageType == .button {
if let index = index,
let payload = message.payloadFromMetadata()?[index],
let type = payload["type"] as? String {
if type == "link" {
let url = payload["url"]
print("\(url)")
return true
}
}
}
}
return false;
}
//KBMConversationViewControllerDelegate cannot be used in Objective-C.
Choosing persistent or temporary storage for the conversation
Customer can switch between using persistent and temporary database for conversation data.
Default is temporary (false).
KBMUserDefaultsHandler.setUsePersistentMessagesStorage(false)
Choosing if messages should refresh on every chat screen open
The SDK fetches the latest message every time the chat-screen is opened.
This functionality can be enabled/disabled.
When disabled, new messages will only be fetched in the event where a push-notification for a new message is received, or a mqtt connection message arrives alerting the sdk of a new message.
Default is enabled (true).
KBMUserDefaultsHandler.setFetchNewOnChatOpen(true)
Detecting Conversation screen lifecycle events
When the BrandMessenger UI framework's conversation screen is used, the following can be implemented to catch when the view appears or disappears.
// viewWillAppear
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.viewWillAppear"), object: nil)
// viewDidAppear
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.viewDidAppear"), object: nil)
// viewWillDisappear
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.viewWillDisappear"), object: nil)
// viewDidDisappear
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.viewDidDisappear"), object: nil)
The conversation screen's back-button tap event can also be captured.
NotificationCenter.default.addObserver(self, selector: #selector(sel), name: NSNotification.Name(rawValue: "KBMConversationViewController.backTapped"), object: nil)
Save video to gallery
If you want to save the downloaded and captured videos to the gallery(Photos album) then use the below setting to enable it:
[BrandMessengerSettings enableSaveVideosToGallery:YES]
BrandMessengerSettings.enableSaveVideosToGallery(flag: true)
Understanding KBMMessage properties
Checking received message or sent message
if ([message.type isEqualToString:KBM_IN_BOX]) {
// Received message
} else {
// Sent message
}
if (message.type == "4") {
// Received message
} else {
// Sent message
}
Checking message content type
You can differentiate between different content types, such as text, location, attachment, contact cards, videos, etc.
if (message.isLocationMessage) {
//Location message contentType
} else if (message.isContactMessage) {
// Contact card attachement contentType
} else if (message.fileMeta) {
if([message.fileMeta.contentType hasPrefix:@"image"]) {
// Image attachemnt message contentType
NSString *filePath = message.imageFilePath; if its downloaded you can get the path
} else if ([message.fileMeta.contentType hasPrefix:@"video"]) {
// Video message contentType
} else if ([message.fileMeta.contentType hasPrefix:@"audio"]) {
// Audio message contentType
}
} else if (message.contentType == KBMMESSAGE_CONTENT_DEFAULT) {
//Message text contentType
} else if (message.contentType == KBMMESSAGE_CHANNEL_NOTIFICATION) {
//Custom message like addedd,removed,created,changed name of channel
}
if (message.isLocationMessage()) {
//Location message contentType
} else if (message.isContactMessage()) {
// Contact card attachement contentType
} else if ((message.fileMeta) != nil) {
if message.fileMeta.contentType?.hasPrefix("image") ?? false {
// Image attachemnt message contentType
let filePath = message.imageFilePath //if its downloaded you can get the path
} else if message.fileMeta.contentType?.hasPrefix("video") ?? false {
// Video message contentType
let filePath = message.imageFilePath //if its downloaded you can get the path
} else if message.fileMeta.contentType?.hasPrefix("audio") ?? false {
// Audio message contentType
let filePath = message.imageFilePath //if its downloaded you can get the path
}
} else if message.contentType == KBMMESSAGE_CONTENT_DEFAULT {
// Message text contentType
}
NOTE:
There are no separate content types for image, video, audio, etc.
These messages come under
message.isDocumentMessage()
and you can check them for theimage
,video
, oraudio
prefix.
To get the message text from KBMMessage
:
message.message
Checking status of the message
For checking the status of the message. These include messages that have been sent to the server, delivered to the user, and delivered and read.
Here is an example:
switch (message.status.intValue) {
case DELIVERED_AND_READ :
{
//Sent message update the ui with read tick
}
break;
case DELIVERED:
{
//Sent message update the UI with Deliverd tick
}
break;
case SENT:
{
//Sent message update the UI with sent tick
}
break;
default:
// Pending state
break;
}
switch message.status {
case DELIVERED_AND_READ:
//Sent message update the ui with read tick
case DELIVERED:
//Sent message update the UI with Deliverd tick
case SENT:
//Sent message update the UI with sent tick
default:
// Pending state
break
}
Location message JSON parsing
You can parse the location message and show it in stack map view:
NSData *objectData = [message.message dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonStringDic = [NSJSONSerialization JSONObjectWithData:objectData
options:NSJSONReadingMutableContainers
error:&error];
NSArray* latLog = [[NSArray alloc] initWithObjects:[jsonStringDic valueForKey:@"lat"],[jsonStringDic valueForKey:@"lon"], nil];
NSString *latLongArgument = [NSString stringWithFormat:@"%@,%@", latLog[0], latLog[1]];
let objectData: Data? = message.message.data(using: String.Encoding.utf8.rawValue)
var jsonStringDic: [AnyHashable : Any]? = nil
if let aData = objectData {
jsonStringDic = try? JSONSerialization.jsonObject(with: aData, options: .mutableContainers) as? [AnyHashable : Any]
}
let latLog = [jsonStringDic?["lat"], jsonStringDic?["lon"]]
let latLongArgument = "\(latLog[0]),\(latLog[1])"
Updated 9 months ago