Flutter iOS端Firebase Messaging推送图片不显示问题求助
Flutter iOS Firebase推送图片不显示:Notification Service Extension配置方案
一、Swift版Notification Service Extension配置步骤
- 添加Extension目标:打开Xcode主项目,点击顶部菜单栏
File > Target > Notification Service Extension,命名(如NotificationService),语言选择Swift,完成创建。
- 添加Extension目标:打开Xcode主项目,点击顶部菜单栏
- 配置Pod依赖:在项目根目录的
Podfile中新增Extension的Target块,添加Firebase Messaging依赖:
- 配置Pod依赖:在项目根目录的
target 'NotificationService' do use_frameworks! pod 'Firebase/Messaging' end
执行终端命令pod install,确保依赖安装完成。
- 替换Extension核心代码:打开
NotificationService.swift,替换默认代码为以下内容,实现图片下载与附件添加逻辑:
- 替换Extension核心代码:打开
import UserNotifications import FirebaseMessaging 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 else { contentHandler(request.content) return } // 从推送payload中获取图片URL(key可根据实际自定义) guard let imageURLString = bestAttemptContent.userInfo["image"] as? String, let imageURL = URL(string: imageURLString) else { contentHandler(bestAttemptContent) return } // 下载图片并添加为通知附件 downloadAttachment(from: imageURL) { attachment in if let attachment = attachment { bestAttemptContent.attachments = [attachment] } contentHandler(bestAttemptContent) } } override func serviceExtensionTimeWillExpire() { // 超时场景下返回原始通知内容 if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } private func downloadAttachment(from url: URL, completion: @escaping (UNNotificationAttachment?) -> Void) { let task = URLSession.shared.downloadTask(with: url) { tempURL, _, error in guard let tempURL = tempURL, error == nil else { completion(nil) return } let fileManager = FileManager.default let tempDir = NSTemporaryDirectory() let fileName = url.lastPathComponent let destinationURL = URL(fileURLWithPath: tempDir).appendingPathComponent(fileName) do { // 清理已存在的旧文件 if fileManager.fileExists(atPath: destinationURL.path) { try fileManager.removeItem(at: destinationURL) } try fileManager.copyItem(at: tempURL, to: destinationURL) // 创建通知附件 let attachment = try UNNotificationAttachment(identifier: "", url: destinationURL, options: nil) completion(attachment) } catch { completion(nil) } } task.resume() } }
- 配置Extension的Info.plist:确保
NSExtension节点下的NSExtensionAttributes包含以下配置(用于通知展开显示):
- 添加键
UNNotificationExtensionInitialContentSizeRatio,值设为0.5(可根据需求调整) - 可选:添加键
UNNotificationExtensionCategory,值与推送payload中的category字段对应
- 配置Extension的Info.plist:确保
- 推送Payload格式要求:必须包含
mutable-content: 1(开启通知可修改权限),并携带图片URL字段,示例:
- 推送Payload格式要求:必须包含
{ "aps": { "alert": { "title": "测试图片推送", "body": "这是一条带图片的通知" }, "mutable-content": 1 }, "image": "https://example.com/your-image.jpg" }
二、Objective-C版报错修复方案
若选择Objective-C语言创建Extension后出现编译/链接报错,按以下步骤修复:
- 配置Pod依赖:同样在
Podfile中为Extension Target添加Firebase依赖:
- 配置Pod依赖:同样在
target 'NotificationService' do use_frameworks! pod 'Firebase/Messaging' end
执行pod install后,重新打开项目。
- 替换Extension核心代码:打开
NotificationService.m,替换为以下代码:
- 替换Extension核心代码:打开
#import "NotificationService.h" #import <FirebaseMessaging/FirebaseMessaging.h> #import <UserNotifications/UserNotifications.h> @interface NotificationService () @property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver); @property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent; @end @implementation NotificationService - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; // 解析推送中的图片URL NSString *imageURLString = self.bestAttemptContent.userInfo[@"image"]; if (imageURLString && imageURLString.length > 0) { NSURL *imageURL = [NSURL URLWithString:imageURLString]; [self downloadAttachmentFromURL:imageURL completion:^(UNNotificationAttachment *attachment) { if (attachment) { self.bestAttemptContent.attachments = @[attachment]; } self.contentHandler(self.bestAttemptContent); }]; } else { self.contentHandler(self.bestAttemptContent); } } - (void)serviceExtensionTimeWillExpire { self.contentHandler(self.bestAttemptContent); } - (void)downloadAttachmentFromURL:(NSURL *)url completion:(void (^)(UNNotificationAttachment *))completion { NSURLSessionDownloadTask *task = [[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL *tempFileURL, NSURLResponse *response, NSError *error) { if (error || !tempFileURL) { completion(nil); return; } NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *tempDir = NSTemporaryDirectory(); NSString *fileName = url.lastPathComponent; NSURL *destinationURL = [NSURL fileURLWithPath:[tempDir stringByAppendingPathComponent:fileName]]; NSError *fileError; if ([fileManager fileExistsAtPath:destinationURL.path]) { [fileManager removeItemAtURL:destinationURL error:&fileError]; } [fileManager copyItemAtURL:tempFileURL toURL:destinationURL error:&fileError]; if (fileError) { completion(nil); return; } NSError *attachmentError; UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" URL:destinationURL options:nil error:&attachmentError]; completion(attachment); }]; [task resume]; } @end
- 排查编译错误:若出现头文件找不到,检查Extension Target的
Build Settings > Framework Search Paths是否包含Pods/Headers/Public路径;若出现链接错误,添加Other Linker Flags为-ObjC。
- 排查编译错误:若出现头文件找不到,检查Extension Target的
- 推送Payload要求与Swift版一致,必须包含
mutable-content:1和图片URL字段。
- 推送Payload要求与Swift版一致,必须包含
内容的提问来源于stack exchange,提问作者Sulaymon Ne'matov
相关产品推荐
相关产品推荐

