# Handling notifications with image

To enable incoming FCM Notifications to display images from the FCM payload on Apple devices, you need to add an additional notification service extension.

# Step 1 - Create a Notification Service Extension

Open Runner.xcodeproj located in ios directory.

  • In Xcode, navigate to: File > New > Target...
  • A modal will appear with a list of potential targets. Scroll down or use the search function to find and select "Notification Service Extension". Click Next.

xcode

  • Provide a product name (e.g., ImageNotification for consistency), set your team, set the language to Swift, and click Finish.
  • Activate the scheme by selecting Activate.

xcode

# Step 2 - Add the Target to the Podfile

Ensure your new extension can access the Firebase/Messaging pod by updating the Podfile:

  • Open the Podfile: ios/Podfile
  • Scroll to the bottom and add the following:
target 'ImageNotification' do
  use_frameworks!
  pod 'Firebase/Messaging'
end
  • Run pod install from the ios directory to install or update your pods.

WARNING

If you see any warnings related to google services while installing pods, try to add pod 'GoogleUtilities' to the target.

target 'ImageNotification' do
  use_frameworks!
  pod 'GoogleUtilities'
  pod 'Firebase/Messaging'
end

# Step 3 - Implement the Extension Helper

Now, ensure everything is set up correctly by invoking the extension helper:

  • Open NotificationService.swift Replace the existing code with the following (you may customize the notification as needed):
import UserNotifications
import UIKit

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(
        _ request: UNNotificationRequest,
        withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
    ) {
        self.contentHandler = contentHandler
        self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        if let fcmOptions = request.content.userInfo["fcm_options"] as? [String: Any],
           let imageURLString = fcmOptions["image"] as? String,
           let imageURL = URL(string: imageURLString) {
            self.downloadImage(from: imageURL) { attachment in
                if let attachment = attachment {
                    self.bestAttemptContent?.attachments = [attachment]
                }
                self.contentHandler?(self.bestAttemptContent ?? request.content)
            }
        } else {
            self.contentHandler?(self.bestAttemptContent ?? request.content)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }

    private func downloadImage(from url: URL, completion: @escaping (UNNotificationAttachment?) -> Void) {
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else {
                completion(nil)
                return
            }
            let tmpDirectory = URL(fileURLWithPath: NSTemporaryDirectory())
            let tmpFile = tmpDirectory.appendingPathComponent(UUID().uuidString + ".jpg")
            do {
                try data.write(to: tmpFile)
                let attachment = try UNNotificationAttachment(identifier: "", url: tmpFile, options: nil)
                completion(attachment)
            } catch {
                completion(nil)
            }
        }.resume()
    }
}

Your device can now display images in notifications by specifying the image option in your FCM payload. Note that there is a 300KB maximum image size limit enforced by the device.