I want to achieve functionality where, if the app is in an inactive or background state, and a message arrives from the sender, the 'mutable-content:1' property is enabled, allowing the Notification Service extension to be called. However, the print logs are not functioning concurrently, and the XMPP Delegate Methods are not being invoked, preventing it from reaching the catch block.
Can anyone please guide me?
NotificationService.swift
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
var extensionContext:UNNotificationServiceExtension?
var isMuted = false
var xmppManager : XMPPManagerNotificationService = XMPPManagerNotificationService()
let sharedXMPPDataClass = SharedXMPPDataNotificationService.sharedInstance
var hostName : String = EMPTY_STRING
var userJIDString : String = EMPTY_STRING
var hostPort : UInt16 = 5222
var password : String = EMPTY_STRING
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
//USER JID
guard let getUserID = SharedUserDefaults.getValue(forKey: SharedUserDefaultsKeys.userJId.rawValue) as? String else {
return
}
userJIDString = getUserID
//XMPP Password
guard let getXmppPwd = SharedUserDefaults.getValue(forKey: SharedUserDefaultsKeys.xmppHostPswd.rawValue) as? String else {
return
}
password = getXmppPwd
//XMPP Host Name
guard let getXmppHost = SharedUserDefaults.getValue(forKey: SharedUserDefaultsKeys.xmppHost.rawValue) as? String else {
return
}
hostName = getXmppHost
print("UserJID:\(userJIDString) \n XMPP Password: \(password) \n XMPP Host Name: \(hostName) \n Host Port: \(hostPort)")
// Check connection status and initiate reconnection
if !self.xmppManager.xmppStream.isConnected && !self.xmppManager.xmppStream.isConnecting {
self.xmppManager.connect()
} else {
self.connectXmpp(userJId: userJIDString, pswd: password)
}
// Modify the notification content here...
// bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
class XMPPManagerNotificationService: NSObject {
var xmppDeliveryRecipts: XMPPMessageDeliveryReceipts!
var xmppStreamManagement: XMPPStreamManagement!
var xmppRoom: XMPPRoom!
var xmppStream: XMPPStream!
//XMPPReconnect will automatically try to reconnect in case of a disconnection, which should address your concern about handling server-side idle time.
var xmppReconnect: XMPPReconnect!
//To implement backgrounding with XMPP in your iOS app, you'll need to integrate PushKit and XEP-0357.
//Implement XEP-0357: This extension allows XMPP to work with PushKit for background notifications.
var xmppPush: XMPPPushModule!
var xmppMUC: XMPPMUCLight!
let sharedXMPPDataClass = SharedXMPPDataNotificationService.sharedInstance
var userJID: XMPPJID!
var password: String = EMPTY_STRING
var hostName: String = EMPTY_STRING
var userJIDString: String = EMPTY_STRING
var hostPort: UInt16 = 5222
override init() {
super.init()
setupXMPPStream()
}
func setupXMPPStream() {
// Initialize XMPPStream
xmppStream = XMPPStream()
// Initialize XMPPReconnect
xmppReconnect = XMPPReconnect()
// Initialize XMPPPushModule
xmppPush = XMPPPushModule()
xmppMUC = XMPPMUCLight()
//USER JID
guard let getUserID = SharedUserDefaults.getValue(forKey: SharedUserDefaultsKeys.userJId.rawValue) as? String else {
return
}
userJIDString = getUserID
if !userJIDString.trimmingCharacters(in: .whitespaces).isEmpty {
do {
guard let userJID = XMPPJID(string: userJIDString, resource: "iOS") else {
return
}
//Save in Singleton Object
sharedXMPPDataClass.userJID = userJID
//Fetch from Singleton
self.hostName = sharedXMPPDataClass.myHostName
self.hostPort = sharedXMPPDataClass.myHostPort
self.password = sharedXMPPDataClass.myPassword
self.userJID = userJID
// Stream Configuration
self.xmppStream.hostName = hostName
self.xmppStream.hostPort = hostPort
self.xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicy.allowed
self.xmppStream.myJID = userJID
self.xmppRoom = XMPPRoom.init(roomStorage: XMPPRoomMemoryStorage(), jid: XMPPJID(string: UserDefaults.standard.getUserJId() ?? EMPTY_STRING) ?? XMPPJID())
xmppRoom.activate(xmppStream)
xmppReconnect.activate(xmppStream)
xmppPush.activate(xmppStream)
xmppMUC.activate(xmppStream)
self.xmppStream.addDelegate(self, delegateQueue: DispatchQueue.main)
self.xmppRoom.addDelegate(self, delegateQueue: DispatchQueue.main)
XMPPMUCLight().addDelegate(self, delegateQueue: DispatchQueue.main)
} catch {
print("Failed to set XMPPJID: \(error.localizedDescription)")
}
} else {
print("userJID is Empty")
}
}
func connect() -> Bool {
// Check if already connected
guard !xmppStream.isConnected else {
return true
}
// Ensure userJID is available
guard let userJID = userJID else {
print("User JID is nil. Unable to connect.")
return false
}
do {
// Set up XMPPStream properties
xmppStream.myJID = userJID
xmppStream.hostName = hostName
xmppStream.hostPort = hostPort
// Disable auto pinging
xmppStream.keepAliveInterval = 0
let xmppPing = XMPPPing()
xmppPing.activate(xmppStream)
xmppPing.respondsToQueries = true
// Connect to XMPP server
try xmppStream.connect(withTimeout: 10)
// Activate message delivery receipts
xmppDeliveryRecipts = XMPPMessageDeliveryReceipts(dispatchQueue: DispatchQueue.main)
xmppDeliveryRecipts.autoSendMessageDeliveryReceipts = true
xmppDeliveryRecipts.autoSendMessageDeliveryRequests = true
xmppDeliveryRecipts.activate(xmppStream)
xmppDeliveryRecipts.addDelegate(self, delegateQueue: DispatchQueue.main)
return true // Successfully initiated connection
} catch let error {
print("Failed to connect to XMPP server: \(error) and myjid is:\(userJID)")
return false // Failed to initiate connection
}
}
func disconnect() {
self.goOffLine()
self.xmppStream.disconnectAfterSending()
}
func goOffLine() {
let presence = XMPPPresence(type: "unavailable")
let priority = DDXMLElement.element(withName: "priority", stringValue: "42") as! DDXMLElement
self.xmppStream.send(presence)
}
func sendMessage(msg:XMPPMessage){
self.xmppStream.send(msg)
}
@objc func sendMsg(notification:Notification){
let msg = notification.userInfo?["msg"] as! XMPPMessage
self.xmppStream.send(msg)
}
}
extension XMPPManagerNotificationService : XMPPStreamDelegate {
// Called when the XMPP stream successfully connects to the server
func xmppStreamDidConnect(_ stream: XMPPStream) {
do {
try stream.authenticate(withPassword: self.password)
self.xmppDeliveryRecipts.autoSendMessageDeliveryReceipts = true
self.xmppDeliveryRecipts.autoSendMessageDeliveryRequests = true
self.xmppDeliveryRecipts.activate(self.xmppStream)
} catch {
print(error.localizedDescription)
}
}
func xmppStreamDidAuthenticate(_ sender: XMPPStream) {
// Called when authentication is successful
print("xmppStreamDidAuthenticate")
}
func xmppMessageDeliveryReceipts(_ xmppMessageDeliveryReceipts: XMPPMessageDeliveryReceipts!, didReceiveReceiptResponse response: XMPPMessage!) {
// Handle receipt response here
print("didReceiveReceiptResponse - XMPPMessageDeliveryReceipts")
}
func xmppMessageDeliveryReceipts(_ xmppMessageDeliveryReceipts: XMPPMessageDeliveryReceipts!, didReceiveDeliveryReceiptFor message: XMPPMessage!) {
// Handle delivery receipt here
print("xmppMessageDeliveryReceipts - XMPPMessageDeliveryReceipts")
}
}