0

One of the issues with firebase_messaging is it's inability to show notifications with images on ios. I'm trying to implement the native way of displaying rich media, but with no results. I lack ios knowledge to actually understand what's happening, and why are they not being shown with the current implementation. Currently only receiving text only push notifications from both FCM console and postman, if notification object is included.

NotificationService

   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)

        defer {
            contentHandler(bestAttemptContent ?? request.content)
        }

        guard let attachment = request.attachment else { return }

        bestAttemptContent?.attachments = [attachment]
    }

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

}

extension UNNotificationRequest {
    var attachment: UNNotificationAttachment? {
        guard let attachmentURL = content.userInfo["image_url"] 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)
    }
}

AppDelegate

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Payload sent from postman

{
    "to": "/topics/red",
    "content_available": true,
    "mutable_content": true,
    "notification": {
        "badge": 9,
        "title": "awd4",
        "mutable-content": true,
        "body": "bod",
        "image_url": "https://www.imgonline.com.ua/examples/jpeg-quality-10.jpg"
    },
    "image_url": "https://www.imgonline.com.ua/examples/jpeg-quality-10.jpg",
    "priority": "high"
}

Is it possible at all, while still receiving callbacks to the dart side, or the only way is fully native FCM integration with platform channels?

saurabh
  • 6,687
  • 7
  • 42
  • 63
Denis Rudenko
  • 667
  • 7
  • 14

2 Answers2

2

Changed content-available from true to false and it worked. Credits to u/imtoori from Reddit.

Denis Rudenko
  • 667
  • 7
  • 14
1

Accepted answer didn't work for me :(

In the payload, I had to send the image url in data for it to work. The payload which worked for me:

{
    "to": "randomDeviceid....",
    "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"
    }
}
saurabh
  • 6,687
  • 7
  • 42
  • 63