Flutter iOS端如何用flutter_local_notifications实现FCM图片通知?
iOS端FCM图片通知实现方案
iOS端要实现FCM图片通知,必须添加iOS Notification Service Extension——因为iOS系统默认通知无法直接处理自定义大图展示,需要通过这个扩展来下载图片并修改通知内容,实现类似Android的大图通知效果。
实现步骤
添加Notification Service Extension到iOS项目
- 打开Xcode,选择你的Flutter iOS项目,点击
File > New > Target,在弹窗里选择Notification Service Extension,命名为NotificationService(可自定义),语言选择Swift,完成创建。 - 创建后Xcode会自动生成
NotificationService.swift文件,我们需要修改这个文件的逻辑。
- 打开Xcode,选择你的Flutter iOS项目,点击
调整FCM消息结构
- 发送FCM推送时,必须在APNs配置里带上
mutable-content: 1,通知内容里要包含图片的URL(比如在data字段里添加image_url: "你的图片地址"),这样Extension才能接收到消息并处理。
- 发送FCM推送时,必须在APNs配置里带上
对应的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
相关产品推荐
相关产品推荐

