Rich push notification not working with FCM in IOS
Asked Answered
O

2

0

I've added UNNotificationServiceExtension and UNNotificationContentExtension in my project for rich push notification.
Please refer the code below which i've added for the same.


Code:

#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

I'm using the following payload

    {
   "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"
   }
}

The problem is i'm not getting the notification. I've used the following tutorial for implementing the rich push notification. I've checked different answers available but none of them worked for me. I've also tried to debug the didReceiveNotificationRequest method by attaching the extension process but the breakpoint not triggered.

https://mobisoftinfotech.com/resources/mguide/ios-10-rich-notifications-tutorial/

Oquassa answered 18/7, 2018 at 12:29 Comment(2)
will you check payload once some keys are missing like "aps","Alert",etc...Petry
Try this solution https://mcmap.net/q/430276/-ios-rich-notification-didreceivenotificationrequest-is-not-firedImmerse
C
0
-(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]);
     }
     */


}

Use above methods and these method available iOS 10 and onwards. for debugging notification service extension please visit below link

Debug Notification Extensions

if you give support your application iOS 9 onwards then you have to put both methods below are for above iOS 10 and you also wrote in your question

- (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);
}

let me know if you have query.

Cheka answered 20/7, 2018 at 5:58 Comment(0)
C
0
@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";
    }
}
Cheka answered 20/7, 2018 at 7:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.