XMPP Delegate Methods are not calling from Notification Service Extension in iOS swift

94 views Asked by At

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")
    }
}
0

There are 0 answers