丰富的推送通知不适用于 IOS 中的 FCM
Posted
技术标签:
【中文标题】丰富的推送通知不适用于 IOS 中的 FCM【英文标题】:Rich push notification not working with FCM in IOS 【发布时间】:2018-07-18 12:29:42 【问题描述】:我在我的项目中添加了UNNotificationServiceExtension
和UNNotificationContentExtension
用于丰富的推送通知。请参考下面我添加的相同代码。
代码:
#import "NotificationService.h"
@interface NotificationService ()
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@end
@implementation NotificationService
NSURLSession *session;
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
NSDictionary *userInfo = request.content.userInfo;
if (userInfo == nil)
[self contentComplete];
return;
if ([userInfo objectForKey:@"pic_url"])
[self loadAttachmentForUrlString:[userInfo objectForKey:@"pic_url"]
completionHandler: ^(UNNotificationAttachment *attachment)
self.bestAttemptContent.attachments = [NSArray arrayWithObjects:attachment, nil];
];
- (void)loadAttachmentForUrlString:(NSString *)urlString
completionHandler:(void (^)(UNNotificationAttachment *))completionHandler
__block UNNotificationAttachment *attachment = nil;
__block NSURL *attachmentURL = [NSURL URLWithString:urlString];
NSString *fileExt = [@"." stringByAppendingString:[urlString pathExtension]];
session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:attachmentURL
completionHandler: ^(NSURL *temporaryFileLocation, NSURLResponse *response, NSError *error)
if (error != nil)
NSLog(@"%@", error.localizedDescription);
else
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *localURL = [NSURL fileURLWithPath:[temporaryFileLocation.path
stringByAppendingString:fileExt]];
[fileManager moveItemAtURL:temporaryFileLocation
toURL:localURL
error:&error];
NSError *attachmentError = nil;
attachment = [UNNotificationAttachment attachmentWithIdentifier:[attachmentURL lastPathComponent]
URL:localURL
options:nil
error:&attachmentError];
if (attachmentError)
NSLog(@"%@", attachmentError.localizedDescription);
completionHandler(attachment);
];
[task resume];
- (void)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.
[self contentComplete];
- (void)contentComplete
[session invalidateAndCancel];
self.contentHandler(self.bestAttemptContent);
@end
我正在使用以下有效负载
"to": "9yJUWBA",
"mutable_content": true,
"category": "myNotificationCategory",
"notification":
"title":"Realtime Custom Push Notifications",
"subtitle":"Now with ios 10 support!",
"body":"Add multimedia content to your notifications"
问题是我没有收到通知。我使用以下教程来实现丰富的推送通知。我检查了可用的不同答案,但没有一个对我有用。我还尝试通过附加扩展进程来调试 didReceiveNotificationRequest 方法,但没有触发断点。
https://mobisoftinfotech.com/resources/mguide/ios-10-rich-notifications-tutorial/
【问题讨论】:
一旦某些键丢失,例如“aps”、“Alert”等,您是否会检查有效负载... 试试这个解决方案***.com/a/50523908/5084797 【参考方案1】:-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
//Called when a notification is delivered to a foreground app.
NSLog(@"Userinfo willPresentNotification%@",notification.request.content.userInfo);
// Print message ID.
/*
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey])
NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
*/
completionHandler(UNNotificationPresentationOptionAlert);
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler
//Called to let your app know which action was selected by the user for a given notification.
NSLog(@"Userinfo didReceiveNotificationResponse%@",response.notification.request.content.userInfo);
// Print message ID.
/*
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey])
NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
*/
使用上述方法,这些方法适用于 iOS 10 及更高版本。 如需调试通知服务扩展,请访问以下链接
Debug Notification Extensions
如果您从 iOS 9 开始支持您的应用程序,那么您必须将以下两种方法都用于 iOS 10 以上,并且您还在问题中写道
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
/*
// Print message ID.
if (userInfo[kGCMMessageIDKey])
NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
*/
// Print full message.
NSLog(@"Userinfo didReceiveRemoteNotification 1 %@",userInfo);
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
/*
// Print message ID.
if (userInfo[kGCMMessageIDKey])
NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
*/
// Print full message.
NSLog(@"Userinfo didReceiveRemoteNotification 2 %@",userInfo);
completionHandler(UIBackgroundFetchResultNewData);
如果您有任何疑问,请告诉我。
【讨论】:
【参考方案2】:@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];
// Modify the notification content here...
self.bestAttemptContent.title = @"";
self.bestAttemptContent.subtitle = @"";
// self.bestAttemptContent.body = [NSString stringWithFormat:@"%@", self.bestAttemptContent.body];
NSDictionary *dictPushNotiData = request.content.userInfo;
NSString *imageURL = @"";
NSString *videoURL = @"";
if(dictPushNotiData[@"xxx_details"])
NSString *jsonString = [dictPushNotiData objectForKey:@"xxx_details"];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
// If Instagram Notification Informations then call InstagramViewController
if(jsonData)
NSMutableDictionary *dictXXX = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
NSLog(@"dictXXX : %@",dictXXX);
//self.bestAttemptContent.title = [NSString stringWithFormat:@"%@", [dictXXX objectForKey:@"xxxx"]];
//self.bestAttemptContent.subtitle = [NSString stringWithFormat:@"%@", [dictXXX objectForKey:@"xxxx"]];
NSString *strBody = @"Notification xxxx x xxxx Post";
if([[dictXXX objectForKey:@"xxxx"] length] > 0)
strBody = [dictXXX objectForKey:@"xxxx"];
self.bestAttemptContent.body = [NSString stringWithFormat:@"%@",strBody];
imageURL = [dictXXX objectForKey:@"xxxx"];
videoURL = [dictXXX objectForKey:@"xxxx"];
NSString *strAttachment = nil;
// if (videoURL.length > 0)
// //Prioritize videos over image
// strAttachment = videoURL;
//
// else
if (imageURL.length > 0)
strAttachment = imageURL;
else
self.contentHandler(self.bestAttemptContent); //Nothing to add to the push, return early.
return;
// If there is an image in the payload, this part
// will handle the downloading and displaying of the image.
if (strAttachment)
NSURL *URL = [NSURL URLWithString:strAttachment];
NSURLSession *LPSession = [NSURLSession sessionWithConfiguration:
[NSURLSessionConfiguration defaultSessionConfiguration]];
[[LPSession downloadTaskWithURL:URL completionHandler: ^(NSURL *temporaryLocation, NSURLResponse *response, NSError *error)
if (error)
NSLog(@"Leanplum: Error with downloading rich push: %@",[error localizedDescription]);
self.contentHandler(self.bestAttemptContent);
return;
NSString *fileType = [self determineType:[response MIMEType]];
NSString *fileName = [[temporaryLocation.path lastPathComponent] stringByAppendingString:fileType];
NSString *temporaryDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] moveItemAtPath:temporaryLocation.path toPath:temporaryDirectory error:&error];
NSError *attachmentError = nil;
UNNotificationAttachment *attachment =
[UNNotificationAttachment attachmentWithIdentifier:@"" URL:[NSURL fileURLWithPath:temporaryDirectory] options:nil error:&attachmentError];
if (attachmentError != NULL)
NSLog(@"Leanplum: Error with the rich push attachment: %@",
[attachmentError localizedDescription]);
self.contentHandler(self.bestAttemptContent);
return;
self.bestAttemptContent.attachments = @[attachment];
NSLog(@"self.bestAttemptContent.attachments : %@",
self.bestAttemptContent.attachments);
self.contentHandler(self.bestAttemptContent);
[[NSFileManager defaultManager] removeItemAtPath:temporaryDirectory error:&error];
] resume];
- (NSString*)determineType:(NSString *) fileType
// Determines the file type of the attachment to append to NSURL.
if ([fileType isEqualToString:@"image/jpeg"])
return @".jpg";
if ([fileType isEqualToString:@"image/gif"])
return @".gif";
if ([fileType isEqualToString:@"image/png"])
return @".png";
else
return @".tmp";
【讨论】:
以上是关于丰富的推送通知不适用于 IOS 中的 FCM的主要内容,如果未能解决你的问题,请参考以下文章
iOS Swift 使用 Firebase 云消息发送丰富的推送通知