You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter iOS端如何用flutter_local_notifications实现FCM图片通知?

iOS端FCM图片通知实现方案

iOS端要实现FCM图片通知,必须添加iOS Notification Service Extension——因为iOS系统默认通知无法直接处理自定义大图展示,需要通过这个扩展来下载图片并修改通知内容,实现类似Android的大图通知效果。

实现步骤

  1. 添加Notification Service Extension到iOS项目

    • 打开Xcode,选择你的Flutter iOS项目,点击File > New > Target,在弹窗里选择Notification Service Extension,命名为NotificationService(可自定义),语言选择Swift,完成创建。
    • 创建后Xcode会自动生成NotificationService.swift文件,我们需要修改这个文件的逻辑。
  2. 调整FCM消息结构

    • 发送FCM推送时,必须在APNs配置里带上mutable-content: 1,通知内容里要包含图片的URL(比如在data字段里添加image_url: "你的图片地址"),这样Extension才能接收到消息并处理。

对应的Swift代码

替换NotificationService.swift的默认代码为以下内容:

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 content = bestAttemptContent,
              let imageUrlString = content.userInfo["image_url"] as? String,
              let imageUrl = URL(string: imageUrlString) else {
            contentHandler(request.content)
            return
        }
        
        // 下载图片到临时目录
        URLSession.shared.downloadTask(with: imageUrl) { [weak self] tempUrl, response, error in
            guard let self = self,
                  let tempUrl = tempUrl,
                  let content = self.bestAttemptContent,
                  error == nil else {
                contentHandler(request.content)
                return
            }
            
            // 将临时文件移动到Extension可访问的目录
            let fileManager = FileManager.default
            let tempDir = NSTemporaryDirectory()
            let fileName = imageUrl.lastPathComponent
            let destUrl = URL(fileURLWithPath: tempDir).appendingPathComponent(fileName)
            
            do {
                if fileManager.fileExists(atPath: destUrl.path) {
                    try fileManager.removeItem(at: destUrl)
                }
                try fileManager.moveItem(at: tempUrl, to: destUrl)
                
                // 创建通知附件
                let attachment = try UNNotificationAttachment(identifier: "image", url: destUrl, options: nil)
                content.attachments = [attachment]
                
                self.contentHandler?(content)
            } catch {
                print("处理图片失败: \(error.localizedDescription)")
                contentHandler(request.content)
            }
        }.resume()
    }
    
    override func serviceExtensionTimeWillExpire() {
        // 超时处理,返回原始通知
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}

注意事项

  • 确保Extension的Bundle ID是主项目Bundle ID加上后缀(比如主项目是com.example.app,Extension就是com.example.app.NotificationService)
  • 图片URL必须是HTTPS的,iOS不允许非HTTPS的资源用于通知附件
  • 注意Extension的内存限制,避免下载过大的图片,防止被系统终止

内容的提问来源于stack exchange,提问作者Jupiter981

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 10:32:42