Last active
November 1, 2023 03:38
-
-
Save lambiengcode/dd0d73bcac57cd6c5875dc0301d54ca2 to your computer and use it in GitHub Desktop.
NotificationService
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // NotificationService.swift | |
| // NotificationService | |
| // | |
| // Created by lambiengcode on 31/10/2023. | |
| // | |
| import UserNotifications | |
| import Intents | |
| 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 { | |
| // Set interruption level to time-sensitive | |
| if #available(iOS 15.0, *) { | |
| bestAttemptContent.interruptionLevel = .timeSensitive | |
| let title = bestAttemptContent.title // The original title | |
| let body = bestAttemptContent.body // The original body | |
| print(title) | |
| // Modify the notification content here to know this works | |
| //REMOVE THIS LATER | |
| bestAttemptContent.title = "\(bestAttemptContent.title) [modified]" | |
| //accessing custom data in the payload from fcm | |
| if let imageURLString = request.content.userInfo["image"] as? String, | |
| let senderThumbnailUrl = URL(string: imageURLString), | |
| let senderThumbnailImageData = try? Data(contentsOf: senderThumbnailUrl), | |
| let senderThumbnailImageFileUrl = try? downloadAttachment(data: senderThumbnailImageData, fileName: senderThumbnailUrl.lastPathComponent), | |
| let senderThumbnailImageFileData = try? Data(contentsOf: senderThumbnailImageFileUrl) { | |
| // profile picture that will be displayed in the notification (left side) | |
| let senderAvatar = INImage(imageData: senderThumbnailImageFileData) | |
| var personNameComponents = PersonNameComponents() | |
| personNameComponents.nickname = title | |
| let senderPerson = INPerson( | |
| personHandle: INPersonHandle( | |
| value: title, | |
| type: .unknown | |
| ), | |
| nameComponents: personNameComponents, | |
| displayName: title, | |
| image: senderAvatar, | |
| contactIdentifier: nil, | |
| customIdentifier: nil, | |
| isMe: false, // this makes the OS recognize this as a sender | |
| suggestionType: .none | |
| ) | |
| // this is just a dummy person that will be used as the recipient | |
| let selfPerson = INPerson( | |
| personHandle: INPersonHandle( | |
| value: "00000000-0000-0000-0000-000000000000", // no need to set a real value here | |
| type: .unknown | |
| ), | |
| nameComponents: nil, | |
| displayName: nil, | |
| image: nil, | |
| contactIdentifier: nil, | |
| customIdentifier: nil, | |
| isMe: true, // this makes the OS recognize this as "US" | |
| suggestionType: .none | |
| ) | |
| let conversationIdentifier = "test-conversation-identifier" | |
| // the actual message. We use the OS to send us ourselves a message. | |
| let incomingMessagingIntent = INSendMessageIntent( | |
| recipients: [selfPerson], | |
| outgoingMessageType: .outgoingMessageText, // This marks the message as outgoing | |
| content: body, // this will replace the content.body | |
| speakableGroupName: nil, | |
| conversationIdentifier: conversationIdentifier, // this will be used as the conversation title | |
| serviceName: nil, | |
| sender: senderPerson, // this marks the message sender as the person we defined above | |
| attachments: [] | |
| ) | |
| incomingMessagingIntent.setImage(senderAvatar, forParameterNamed: \.sender) | |
| let interaction = INInteraction(intent: incomingMessagingIntent, response: nil) | |
| interaction.direction = .incoming | |
| if let bestAttemptContents = try? bestAttemptContent.updating(from: incomingMessagingIntent) as? UNMutableNotificationContent { | |
| // Deliver the modified content if available | |
| contentHandler(bestAttemptContents) | |
| return | |
| } | |
| } | |
| } | |
| return super.didReceive(request, withContentHandler: contentHandler) | |
| } | |
| } | |
| 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) | |
| } | |
| } | |
| func downloadAttachment(data: Data, fileName: String) -> URL? { | |
| // Create a temporary file URL to write the file data to | |
| let fileManager = FileManager.default | |
| let tmpSubFolderName = ProcessInfo.processInfo.globallyUniqueString | |
| let tmpSubFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(tmpSubFolderName, isDirectory: true) | |
| do { | |
| // prepare temp subfolder | |
| try fileManager.createDirectory(at: tmpSubFolderURL, withIntermediateDirectories: true, attributes: nil) | |
| let fileURL: URL = tmpSubFolderURL.appendingPathComponent(fileName) | |
| // Save the image data to the local file URL | |
| try data.write(to: fileURL) | |
| return fileURL | |
| } catch let error { | |
| print("error \(error)") | |
| } | |
| return nil | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment