Notification Support
push notifications in handover first provide the sdk with the apple push notification token using kindlysdk setapnsdevicetoken( devicetoken data) kindlysdk setapnsdevicetoken( devicetoken string) when a push notification is received forward the notification to sdk using kindlysdk notificationreceived( userinfo \[anyhashable any]) kindlysdk notificationreceived( notification unnotification) the sdk will double check if notification type is a kindly notification before handling it check if a notification is from kindly to determine if a notification should be handled by the kindly sdk or another notification provider (like mparticle or braze), use the following helper method let iskindlynotification = kindlysdk iskindlynotification( userinfo \[anyhashable any]) this can be particularly useful when integrating with multiple push notification providers example usage func application( application uiapplication, didreceiveremotenotification userinfo \[anyhashable any], fetchcompletionhandler completionhandler @escaping (uibackgroundfetchresult) > void) { if kindlysdk iskindlynotification(userinfo) { // handle with kindly sdk kindlysdk notificationreceived(userinfo) } else { // handle with another notification provider (e g , mparticle/braze) othernotificationprovider handlenotification(userinfo) } completionhandler( newdata) } when a notification is clicked kindlysdk notificationresponsereceived( response unnotificationresponse) when the sdk displays the notification kindly silent pushes are encrypted; the sdk decrypts each one and presents a local banner with the decrypted title/body â except when the user is already actively reading the chat conversation the display rule is app state active screen sdk presents the banner? background any â
yes foreground chat conversation â no (the user can already see the message) foreground settings, language, image preview, host app screens, etc â
yes the sdk ships kindlysdk notificationdelegate , which applies this rule; assign it to unusernotificationcenter current() delegate with your own delegate, call kindlysdk notificationwillpresent( completionhandler ) from willpresent for kindly notifications with the notification service extension below, killed and background states are handled by ios itself with the decrypted text intercepting notifications ( shouldhandlenotification ) every kindly silent push that the sdk successfully decrypts is forwarded to the host app via the shouldhandlenotification(notification ) delegate method â regardless of foreground/background state or which screen is on top use it to run side effects (analytics, logging, in app indicators) or to take over the presentation entirely with your own ui scenario result delegate not set sdk presents the notification (subject to the display rule above) shouldhandlenotification returns true (default) sdk presents the notification (subject to the display rule above) shouldhandlenotification returns false sdk does not present anything â your app handles it the delegate receives an externalnotification containing the decrypted fields plus the original userinfo for any extra fields your backend attached public struct externalnotification { public let id string // decrypted chat id public let title string // decrypted title public let body string // decrypted body public let userinfo \[anyhashable any] // original apns userinfo (aps, custom keys, âĻ) } implementation 1\ set the delegate kindlysdk delegate = self 2\ conform to kindlychatclientdelegate extension viewcontroller kindlychatclientdelegate { func shouldhandlenotification(notification externalnotification) > bool { // always log every kindly notification, regardless of who presents it analytics track("kindly notification received", id notification id) // example take over presentation when the app is in a custom in app inbox if isshowingcustominbox { custominbox append(notification) return false // sdk does not present its banner } return true // let the sdk present the banner } } notes the method has a default implementation that returns true , so you only need to implement it if you want to observe or intercept notifications the callback fires for every successfully decrypted kindly push â it is not gated by the sdk's foreground/chat screen display rule use it for analytics that need to run even when the sdk is on screen the polarity matches shouldhandlelink returning true means "the sdk should handle this", returning false means "i'll handle it myself" returning false only suppresses the local banner â the underlying message has already been delivered to the chat session via the websocket / /latest endpoint, so it will appear in the chat history when the user opens it notification service extension (recommended, sdk 3 0 10+) with an extension in your app, kindly sends a visible push ( aps alert + mutable content 1 ) instead of a silent one ios runs the extension before showing the banner, in every app state including when the app was killed, and the extension decrypts the kindly payload so the banner shows the real title and text silent pushes are rate limited by ios and never delivered to a force quit app; visible pushes have neither problem the switch is per bot once your app ships the extension, ask your kindly contact to enable alert notifications for your bot kindly only sends the visible push to devices on sdk 3 0 10 or newer, so older app versions keep working exactly as before setup file â new â target â notification service extension , embedded in your app replace the generated class with import kindly final class notificationservice kindlynotificationserviceextension {} link kindly into the extension target the linker warning about extension safety is expected on both the app target and the extension target add the keychain sharing capability with the same group, your app's bundle id \<key>keychain access groups\</key> \<array> \<string>$(appidentifierprefix)ai kindly example\</string> \</array> tell kindly the app version that ships the extension what changes at runtime push app state user sees visible killed or background one banner with the decrypted text, produced by the extension visible foreground, on the chat conversation nothing visible foreground, elsewhere one banner with the decrypted text silent any what it sees today without the extension a visible push shows the generic placeholder in the background and the sdk's own decrypted banner in the foreground ciphertext is never shown handling the tap tapping a kindly banner opens the chat ( kindlysdk openchatonnotificationtap , default true ) a tap that launched the app opens the chat once start() has run the remembered tap is replayed only when start() runs within 60 seconds of it; after that it is dropped, with a log line your own delegate if you keep your own unusernotificationcenterdelegate , call kindlysdk notificationwillpresent(notification, completionhandler ) for kindly notifications from willpresent so the sdk's display rule applies api open class kindlynotificationserviceextension unnotificationserviceextension { open func customize( content unmutablenotificationcontent, payload kindlypushdecryption decryptedpayload?) } public enum kindlypushdecryption { public struct decryptedpayload { public let chatid string; public let title string; public let body string } public static func iskindlynotification( userinfo \[anyhashable any]) > bool public static func decrypt(userinfo \[anyhashable any]) > decryptedpayload? public static func apply( payload decryptedpayload, to content unmutablenotificationcontent) public static func isdecrypted( userinfo \[anyhashable any]) > bool } decrypt returns nil when the push is not kindly's, a field is missing, the keychain has no key yet, or decryption fails; the extension then leaves the placeholder in place see also the push notifications reference (push md) https //kindly ai github io/sdk chat ios sources/push md has the complete walkthrough, including hosts with an existing extension for another provider