Files

157 lines
6.1 KiB
Swift

//
// NotificationService.swift
// notificationServiceAppExtension
//
// Created by QuentinArguillere on 26/07/2021.
//
import UserNotifications
import linphonesw
var APP_GROUP_ID = "group.org.linphone.tutorials.notification"
var LINPHONE_DUMMY_SUBJECT = "dummy subject"
struct MsgData: Codable {
var from: String?
var body: String?
var subtitle: String?
var callId: String?
var localAddr: String?
var peerAddr: String?
}
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
var lc: Core?
static var logDelegate: LinphoneLoggingServiceManager!
static var log: LoggingService!
func stopCore() {
NotificationService.log.message(message: "stop core")
if let lc = lc {
lc.stop()
}
}
// This function will be called when the app received a notification while in background // closed
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
NSLog("[notificationServiceAppExtension] start notificationServiceAppExtension")
if let bestAttemptContent = bestAttemptContent {
NSLog("[notificationServiceAppExtension] create core")
let config = Config.newForSharedCore(appGroupId: APP_GROUP_ID, configFilename: "linphonerc", factoryConfigFilename: "")
if (NotificationService.log == nil) {
NotificationService.log = LoggingService.Instance /*enable liblinphone logs.*/
NotificationService.logDelegate = try! LinphoneLoggingServiceManager(config: config!, log: NotificationService.log, domain: "notificationServiceAppExtension")
}
// We are creating a shared core, which will use the configuration file form the main app thanks to the App Group
lc = try! Factory.Instance.createSharedCoreWithConfig(config: config!, systemContext: nil, appGroupId: APP_GROUP_ID, mainCore: false)
NotificationService.log.message(message: "received push payload : \(bestAttemptContent.userInfo.debugDescription)")
// Flexisip sends 2 types of remote push : invitation to a group chatroom, or receiving a chat message
if let chatRoomInviteAddr = bestAttemptContent.userInfo["chat-room-addr"] as? String, !chatRoomInviteAddr.isEmpty {
NotificationService.log.message(message: "fetch chat room for invite, addr: \(chatRoomInviteAddr)")
// create a chatroom with the address we received
let chatRoom = lc!.getNewChatRoomFromConfAddr(chatRoomAddr: chatRoomInviteAddr)
if let chatRoom = chatRoom {
stopCore()
NotificationService.log.message(message: "chat room invite received")
// Update notification body to display custom information
bestAttemptContent.title = "You have been invited to a chatroom"
if (chatRoom.hasCapability(mask:ChatRoomCapabilities.OneToOne.rawValue)) {
if (chatRoom.peerAddress?.displayName.isEmpty != true) {
bestAttemptContent.body = chatRoom.peerAddress!.displayName
} else {
bestAttemptContent.body = chatRoom.peerAddress!.username
}
} else {
bestAttemptContent.body = chatRoom.subject
}
contentHandler(bestAttemptContent)
return
}
} else if let callId = bestAttemptContent.userInfo["call-id"] as? String {
NotificationService.log.message(message: "fetch msg for callid ["+callId+"]")
// Get message content from the call id we received
let message = lc!.getNewMessageFromCallid(callId: callId)
if let message = message {
func parseMessage(message: PushNotificationMessage) -> MsgData? {
let content = message.isText ? message.textContent : "🗻"
let fromAddr = message.fromAddr?.username
let callId = message.callId
let localUri = message.localAddr?.asStringUriOnly()
let peerUri = message.peerAddr?.asStringUriOnly()
var msgData = MsgData(from: fromAddr, body: "", subtitle: "", callId:callId, localAddr: localUri, peerAddr:peerUri)
if let subject = message.subject as String?, subject != "" {
msgData.subtitle = subject
msgData.body = fromAddr! + " : " + content
} else {
msgData.subtitle = fromAddr
msgData.body = content
}
NotificationService.log.message(message: "received msg size : \(content.count) \n")
return msgData;
}
let msgData = parseMessage(message: message)
stopCore()
// Fill notification body with custom informations
bestAttemptContent.title = "Message received"
if let subtitle = msgData?.subtitle {
bestAttemptContent.subtitle = subtitle
}
if let body = msgData?.body {
bestAttemptContent.body = body
}
bestAttemptContent.userInfo.updateValue(msgData?.callId as Any, forKey: "CallId")
bestAttemptContent.userInfo.updateValue(msgData?.from as Any, forKey: "from")
bestAttemptContent.userInfo.updateValue(msgData?.peerAddr as Any, forKey: "peer_addr")
bestAttemptContent.userInfo.updateValue(msgData?.localAddr as Any, forKey: "local_addr")
contentHandler(bestAttemptContent)
return
} else {
NotificationService.log.message(message: "Message not found for callid ["+callId+"]")
}
}
serviceExtensionTimeWillExpire()
}
}
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.
NotificationService.log.warning(message: "serviceExtensionTimeWillExpire")
stopCore()
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
NSLog("[notificationServiceAppExtension] serviceExtensionTimeWillExpire")
if let chatRoomInviteAddr = bestAttemptContent.userInfo["chat-room-addr"] as? String, !chatRoomInviteAddr.isEmpty {
bestAttemptContent.title = "You have been invited to a chatroom"
} else {
bestAttemptContent.title = "You have received a message"
}
contentHandler(bestAttemptContent)
}
}
}