I have been looking for a solution for this since quite a while. But I am not able to find anything. I have implemented Push Notifications for iOS using FCM. But I don't know if FCM supports iOS 10 rich notifications. If it does, I didn't find code to implement it. Thanks in advance.
I have the same question why rich notification not working.. and the problem is with FCM mutable-content
payload .. it turns in to gcm.notification.mutable-content
when payload receives and that's why there is a problem which is not resolved yet.
For more information, you can check this issue from github.
Its resolved now.. you can check that link and also check this answer AL.
Just an update in relation with @ElCaptainv2.0's answer.
The mutable_content
has been added for FCM:
Currently for iOS 10+ devices only. On iOS, use this field to represent mutable-content in the APNS payload. When a notification is sent and this is set to true, the content of the notification can be modified before it is displayed, using a Notification Service app extension. This parameter will be ignored for Android and web.
Note: The parameter value should be boolean
, not Integer
.
It was also mentioned in the GitHub thread just a few hours ago by kroikie.
mutable_content
in fcm payload but it's doesn't work. When I try to check my code with APNS it's work fine. {"to": "dWB537Nz....", "data": { "message": "Offer!", "mediaUrl": "HTTPS url" }, "notification": { "body": "Enter your message", "sound": "default", "click_action": "reminder", "content-available": 1, "mutable-content": 1 } }
–
Ludendorff mutable_content
should be declared outside notification
. Same with content_available
. Note that for FCM, it has underscores (_
) instead of dashes (-
). –
Gaillard mutable_content
has to be set to 'true'
. I thought it was supposed to be set to '1'
–
Pressure The Following worked for me (February 2023)
Step 1 - Add a notification service extension
Step 2 - Add Target to Podfile
Step 3 - Use Extension Helper
Converted to Swift:
//
// NotificationService.swift
// RichNotification
//
import UserNotifications
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)
guard let bestAttemptContent = bestAttemptContent,
let attachmentURLAsString = bestAttemptContent.userInfo["image"] as? String,
let attachmentURL = URL(string: attachmentURLAsString) else {
return
}
downloadImageFrom(url: attachmentURL) { (attachment) in
if let attachment = attachment {
bestAttemptContent.attachments = [attachment]
contentHandler(bestAttemptContent)
}
}
}
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)
}
}
private func downloadImageFrom(url: URL, with completionHandler: @escaping (UNNotificationAttachment?) -> Void) {
let task = URLSession.shared.downloadTask(with: url) { (downloadedUrl, response, error) in
// 1. Test URL and escape if URL not OK
guard let downloadedUrl = downloadedUrl else {
completionHandler (nil)
return
}
// 2. Get current's user temporary directory path
var urlPath = URL(fileURLWithPath: NSTemporaryDirectory ())
// 3. Add proper ending to url path, in the case jpg (The system validates the content of attached files before scheduling the corresponding notification request. If an attached file is corrupted,
let uniqueURLEnding = ProcessInfo.processInfo.globallyUniqueString + ".jpg"
urlPath = urlPath.appendingPathComponent (uniqueURLEnding)
// 4. Move downloadedUrl to newly created urlPath
try? FileManager.default.moveItem(at: downloadedUrl, to: urlPath)
// 5. Try adding getting the attachment and pass it to the completion handler
do {
let attachment = try UNNotificationAttachment (identifier: "picture", url: urlPath, options: nil)
completionHandler(attachment)
}
catch {
completionHandler(nil)
}
}
task.resume()
}
}
extension UNNotificationRequest {
var attachment: UNNotificationAttachment? {
guard let attachmentURL = content.userInfo["image"] as? String, let imageData = try? Data(contentsOf: URL(string: attachmentURL)!) else {
return nil
}
return try? UNNotificationAttachment(data: imageData, options: nil)
}
}
extension UNNotificationAttachment {
convenience init(data: Data, options: [NSObject: AnyObject]?) throws {
let fileManager = FileManager.default
let temporaryFolderName = ProcessInfo.processInfo.globallyUniqueString
let temporaryFolderURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(temporaryFolderName, isDirectory: true)
try fileManager.createDirectory(at: temporaryFolderURL, withIntermediateDirectories: true, attributes: nil)
let imageFileIdentifier = UUID().uuidString + ".jpg"
let fileURL = temporaryFolderURL.appendingPathComponent(imageFileIdentifier)
try data.write(to: fileURL)
try self.init(identifier: imageFileIdentifier, url: fileURL, options: options)
}
}
cURL to send push notification via Firebase/FCM
curl --location --request POST 'https://fcm.googleapis.com/fcm/send' \
--header 'Authorization: key=<YOUR FCM KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"to": "fcm token for device or channel id",
"content_available": true,
"mutable_content": true,
"notification": {
"title": "Notification With Image",
"mutable-content": true,
"body": "Test Message "
},
"data": {
"image": "https://upload.wikimedia.org/wikipedia/commons/1/16/HDRI_Sample_Scene_Balls_%28JPEG-HDR%29.jpg"
}
}'
I was working on this for hours and hours and hours and hours. All my notifications worked fine except the rich notification
image would never show. Here is the answer is plain english:
Change this:
"mutable-content": 1
// wrong
To this:
"mutable_content": true
// correct
Here is the outgoing payload:
"aps": {
"alert": {
"title": "Hello",
"body": "What do you think of this image?"
},
"mutable_content": true
},
"media-url": "https://firebasestorage.googleapis.com/....."
© 2022 - 2024 — McMap. All rights reserved.