Notifications (BrandMessengerCore Custom UI)

Learn about notifications using the Brand Messenger UI

Build your UI from scratch - Message Notification

This section describes how to receive push notifications for your chat within your app.

Setting up APNs Certificates

Brand Messenger server sends the payload to Apple servers which then sends push notifications to your user's device.

Creating APNs certificates

For Apple to send these notifications, you must create an APN certificate in your Apple developer account.

  1. Visit this link, Apple Push Notification service SSL (Sandbox)
1372
  1. Visit this link, select Apple Push Notification service SSL (Sandbox & Production), and click Create.
1440

📘

Note: Supported format for the APNS certificate is .p12

The p12 files are required to for authentication with Apple servers and for sending APNs push notifications to devices. This section shows you how to export p12 file from Keychains for uploading to the Brand Messenger.

Follow these steps for export Apple push service and APNs Development iOS certificate p12 file:

For Apple push service export :

A. Open Keychain Access on your Mac and go to login > Select My Certificates.

B. Find the Apple push services certificate and which you added, right-click on the certificate, and then select the Export option from the menu to get a .p12 file. Type a name for the file and save it with the password.

1129

For APNs Development iOS export :

A. Open Keychain Access on your Mac and go to login > Select My Certificates.

B. Find the APNs Development iOS certificate and which you added, right-click on the certificate, and then select the Export option from the menu to get a .p12 file. Type a name for the file and save it with the password.

1128

Upload APNs Certificates

Contact Khoros Support and provide the exported p12 files with password to upload the notification certificates.

Updating Capabilities

After you finish setting up APNs, you must enable push notifications within your project.
Click on your project, click Capabilities, and select Enable.

  1. Push Notifications
  2. Background Modes - Fetch and Remote notification
941 933

Push Notifications

To set up push notification, find the "AppDelegate" file in your project and follow the instructions below.

❗️

Setup BrandMessengerClient

Note: You need to setup BrandMessengerClient before using the methods refer to this link

a) Send device token to Brand Messenger server:

In your AppDelegate’s didRegisterForRemoteNotificationsWithDeviceToken method, send device registration to BrandMessenger server after you get deviceToken from APNs.

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)
   deviceToken {                
  
    const unsigned *tokenBytes = [deviceToken bytes];            
    NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",                 
    ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),             
    ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),             
    ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];              
    
    NSString *apnDeviceToken = hexToken;            
    NSLog(@"apnDeviceToken: %@", hexToken);                            

    if (![[KBMUserDefaultsHandler getApnDeviceToken] isEqualToString:apnDeviceToken]) {                         
       KBMRegisterUserClientService *registerUserClientService = [[KBMRegisterUserClientService alloc] init];          
       [registerUserClientService updateApnDeviceTokenWithCompletion
       :apnDeviceToken withCompletion:^(KBMRegistrationResponse
       *rResponse, NSError *error) {   
       
       if (error) {          
            NSLog(@"%@",error);             
            return;           
       }              
        NSLog(@"Registration response%@", rResponse);                         
    }]; 
  } 
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

        NSLog("Device token data :: \(deviceToken.description)")

        var deviceTokenString: String = ""
        for i in 0..<deviceToken.count {
            deviceTokenString += String(format: "%02.2hhx", deviceToken[i] as CVarArg)
        }

        NSLog("Device token :: \(deviceTokenString)")

        if (KBMUserDefaultsHandler.getApnDeviceToken() != deviceTokenString) {
            let registerUserClientService: KBMRegisterUserClientService = KBMRegisterUserClientService()
            registerUserClientService.updateApnDeviceToken(withCompletion: deviceTokenString, withCompletion: { (response, error) in
               if error != nil {
                   NSLog("Error in Registration: %@", error)
               }
               NSLog("Registration Response :: \(response)")
            })
        }
    }

b) Handling app launch on notification:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
      [KBMRegisterUserClientService isAppUpdated];
      if (launchOptions != nil) {
        NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        if (dictionary != nil) {
            NSLog(@"Launched from push notification: %@", dictionary);
            [self.brandMessengerClient notificationArrivedToApplication:application withDictionary:dictionary];
        }
    }

    return YES;
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        KBMRegisterUserClientService.isAppUpdated()
        if (launchOptions != nil) {
            let dictionary = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? NSDictionary
            
            if (dictionary != nil) {
                brandMessengerClient?.notificationArrived(to: application, with: launchOptions)
            }
        }
        
        return true
 }

c) AppDelegate changes to observe background/foreground notification:

Background Notification

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
    
    [self.brandMessengerClient notificationArrivedToApplication:application withDictionary:userInfo];
    completionHandler(UIBackgroundFetchResultNewData);
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{

    KBMPushNotificationService * service = [[KBMPushNotificationService alloc]init];

    NSDictionary * userInfo = response.notification.request.content.userInfo;

    if ([service isBrandMessengerChatNotification: userInfo]) {
        [self.brandMessengerClient notificationArrivedToApplication:[UIApplication sharedApplication] withDictionary:response.notification.request.content.userInfo];
        completionHandler();
    } else {
        //Handle your noticiation

        completionHandler();
    }

}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler
        completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("Received notification With Completion :: \(userInfo.description)")
        
        brandMessengerClient?.notificationArrived(to: application, with: userInfo)
        completionHandler(UIBackgroundFetchResult.newData)
    }
    
 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo

        let service = KBMPushNotificationService()
        if service.isBrandMessengerChatNotification(userInfo) {
            brandMessengerClient?.notificationArrived(to: UIApplication.shared, with: userInfo)
            completionHandler()
            return
        }
        completionHandler()
    }

d) Add the code shown below into applicationWillEnterForeground of appDelegate to sync messages

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

    [KBMMessageService getLatestMessageForUser:[KBMUserDefaultsHandler getDeviceKeyString] withDelegate:self withCompletion:^(NSMutableArray *messages, NSError *error) {

    }];

}
func applicationDidBecomeActive(_ application: UIApplication) {

        KBMMessageService.getLatestMessage(forUser: KBMUserDefaultsHandler.getDeviceKeyString(), with: self) { (array, error) in

        }
    }

if messages are there, you can add messages in your view controller after the messages are synced.

e) Save Context when app terminates

- (void)applicationWillTerminate:(UIApplication *)application {
    [[KBMDBHandler sharedInstance] saveContext];
}
func applicationWillTerminate(application: UIApplication) {
    KBMDBHandler.sharedInstance().saveContext()
}

Disable Notification

To disable the incoming push notification alert or only notification sound, you need to update notification mode. The possible values for the notification mode are shown below.

[KBMRegisterUserClientService updateNotificationMode:modeValue withCompletion:^(KBMRegistrationResponse *response, NSError *error) {
   NSLog(@"RESPONSE :: %@",response.message);
   NSLog(@"RESPONSE_ERROR :: %@",error.description);
   if (!error) {
      [KBMUserDefaultsHandler setNotificationMode:modeValue];
   } else {
     //Error updating notification mode...
   }
}];
KBMRegisterUserClientService.updateNotificationMode(modeValue, withCompletion: {
	response, error in
	if (error != nil) {
     //Error updating notification mode...
	} else {
		  KBMUserDefaultsHandler.setNotificationMode(modeValue)
	}
})
Notification ModeExplanation
0Enable notification with sound (Default)
1Enable notification without sound
2Disable notification (No Alert)

Custom Push Notification messages

When using generic push-notifications, the SDK Provides a way for the developer to customize the title and text of the incoming push-notification displayed in the iOS Banner.
This requires the following steps.

1) Create new Notification Service Extension target

From Xcode, in project TARGETS, add a new target of type Notification Service Extension.
Official instructions are https://developer.apple.com/documentation/usernotifications/modifying_content_in_newly_delivered_notifications?language=objc
This will create a new NotificationService file.

2) Update NotificationService file

Update the file to look like the following

import UserNotifications

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            // Modify the notification content here...

            /// Brand messenger notification
            if isBrandMessengerChatNotificaiton(content: request.content) {

                bestAttemptContent.title = NSLocalizedString("GenericNotificationTitle", tableName: nil, bundle: .main, value: "Chat", comment: "")

                bestAttemptContent.body = NSLocalizedString("GenericNotificationContentText", tableName: nil, bundle: .main, value: "You have a new message.", comment: "")
            }
          
            contentHandler(bestAttemptContent)
        }
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }

    /// Use this method to check for notification for Brand Messenger.
    /// - Parameter content:Pass `UNNotificationContent` object for notification userInfo payload.
    /// - Returns: Returns `true` if it's a Brand Messenger notification otherwise `false`.
    func isBrandMessengerChatNotificaiton(content: UNNotificationContent) -> Bool {

        let prefix = "BRANDMESSENGER_"
        let notificationKey = "AL_KEY"

        guard let brandMessengerPrefix = content.userInfo[notificationKey] as? String, brandMessengerPrefix.hasPrefix(prefix) else {
            return false

        }
        return true
    }
}

3) Bundle Localizable.strings into the created extension

In Xcode, in Project settings, select the newly created Notification Service Extension TARGET. Go to Build Phases tab, and in Copy Bundle Resources, add the app's Localizable.strings file. If one does not already exist, create one and add.

4) Modify the notification strings

In the Localizable.strings file, add values for GenericNotificationTitle and GenericNotificationContentText to set them on the incoming push-notification banners.

GenericNotificationTitle = "Khoros Chat";
GenericNotificationContentText = "You have a new message!";