相关文章推荐
知识渊博的花卷  ·  sqoop ...·  8 月前    · 
豪爽的吐司  ·  Python ...·  11 月前    · 
开朗的风衣  ·  解决python3 ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm developing an iPhone application using objective-c. The basic push notification is working properly. Now I want to add rich notification in my app but I cannot get the didReceiveNotificationRequest fired in the NotificationService.

Here is the notification payload I receive on Appdelegate:

https://image.ibb.co/ndA2Qo/grab.png

Here is the NotificationService.m file;

#import "NotificationService.h"
#import "Common.h"
@interface NotificationService ()
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
NSLog(@"didReceiveNotificationRequest");
// Modify the notification content here...
// load the attachment
NSDictionary *userInfo = request.content.userInfo;
NSString *imageURL = [userInfo valueForKey:@"thumbnail_image"];
NSArray *parts = [imageURL componentsSeparatedByString:@"."];
NSString *extension = [parts lastObject];
[self loadAttachmentForUrlString:imageURL
                        withExtension:extension
               completionHandler:^(UNNotificationAttachment *attachment) {
                   if (attachment) {
                       self.bestAttemptContent.attachments = [NSArray arrayWithObject:attachment];
                   //self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title];
                   self.contentHandler(self.bestAttemptContent);
- (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.contentHandler(self.bestAttemptContent);
- (void)loadAttachmentForUrlString:(NSString *)urlString withExtension:(NSString *)extension completionHandler:(void(^)(UNNotificationAttachment *))completionHandler  {
__block UNNotificationAttachment *attachment = nil;
NSURL *attachmentURL = [NSURL URLWithString:urlString];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[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:extension]];
                    [fileManager moveItemAtURL:temporaryFileLocation toURL:localURL error:&error];
                    NSError *attachmentError = nil;
                    attachment = [UNNotificationAttachment attachmentWithIdentifier:@"" URL:localURL options:nil error:&attachmentError];
                    if (attachmentError) {
                        NSLog(@"%@", attachmentError.localizedDescription);
                completionHandler(attachment);
            }] resume];

What am I missing?

Please advice,

Semih

The existing answer states that you should set content-available to 1, that NSLog does not work in extensions and the background thread is an issue. These are not right.

  • content-available:1 has no relevance to a notification service extension, for that to be fired up you need mutable-content:1.

  • NSLog works fine in extensions, it is handy to use the OS console when troubleshooting.

  • There is no problem with downloading an image in a background thread.

  • Try looking in the OS Console to see what might be happening (launch console.app on your Mac, plug in your device and select it on the left, and see what goes by when you send a push. Even without your NSLog you should see the OS trying to find and launch an extension like:

    default 10:38:53.925889 -0400   SpringBoard [com.you.whatever] Remote 
    notification request 386D-4968 can be modified: 1
    default 10:38:53.926227 -0400   SpringBoard [com.you.whatever] Trying to find extension for bundle
    info    10:38:53.942366 -0400   pkd Candidate plugin count: 1, info: (
    "com.you.whatever.NotificationServiceExtension(1.0.0) 2765CB-8244DD--B83D-20CB148BCEF6")
    default 10:38:53.945090 -0400   SpringBoard [com.you.whatever] Extension can modify push notification request 386D-4968? YES
    

    If you don't see success there maybe something is wrong with your project setup, maybe try recreating the target in XCode (do via File -> New -> Target, select Notification Service Extension).

    You are downloading the image in background thread which is causing the issue in Rich Push Notification case. If you want you can try with this framework

    Also Add "content-available":1 in your aps

    OR you can try downloading like this,

    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *))contentHandler {
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
        self.bestAttemptContent.title = [NSString stringWithFormat:@"%@",request.content.title];
        self.bestAttemptContent.body = [NSString stringWithFormat:@"%@",request.content.body];
        NSString *attachmentUrlString = [NSString stringWithFormat:@"%@",[request.content.userInfo valueForKey:@"thumbnail_image"]];
        if (![attachmentUrlString isKindOfClass:[NSString class]]) {
            [self failEarly];
            return;
        NSURL *url = [NSURL URLWithString:attachmentUrlString];
        if (!url) {
            [self failEarly];
            return;
        NSData *data = [NSData dataWithContentsOfURL:url];
        if (!data) {
            [self failEarly];
            return;
        NSString *identifierName = [self getIdentifierName:attachmentUrlString];
        NSString *tmpSubFolderName = [[NSProcessInfo processInfo] globallyUniqueString];
        self.bestAttemptContent.attachments = [NSArray arrayWithObject:[self create:identifierName andData:data withOptions:nil andTmpFolderName:tmpSubFolderName]] ;
        self.contentHandler(self.bestAttemptContent);
    -(void)failEarly {
        self.contentHandler(self.bestAttemptContent);
    -(NSString *)getIdentifierName:(NSString *)fileURL
        NSString *identifierName = @"image.jpg";
        if (fileURL) {
            identifierName = [NSString stringWithFormat:@"file.%@",fileURL.lastPathComponent];
        return identifierName;
    -(UNNotificationAttachment *)create:(NSString *)identifier andData:(NSData *)data withOptions:(NSDictionary *)options andTmpFolderName:(NSString *)tmpSubFolderName {
        NSString *fileURLPath = NSTemporaryDirectory();
        NSString *tmpSubFolderURL = [fileURLPath stringByAppendingPathComponent:tmpSubFolderName];
        NSError *error;
        [[NSFileManager defaultManager] createDirectoryAtPath:tmpSubFolderURL withIntermediateDirectories:TRUE attributes:nil error:&error];
        if(!error) {
            NSString *fileURL = [tmpSubFolderURL stringByAppendingPathComponent:identifier];
            [data writeToFile:fileURL atomically:YES];
            UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:identifier URL:[NSURL fileURLWithPath:fileURL] options:options error:&error];
            return attachment;
        return nil;
    - (void)serviceExtensionTimeWillExpire {
        self.contentHandler(self.bestAttemptContent);
                    Thanks for the reply, I'll try it and get back to you. However, I still wonder why NSLog(@"didReceiveNotificationRequest") does not log anything on the log window. At least it should log if didReceiveNotificationRequest is hit, am I right?
    – Semih Akbas
                    May 28, 2018 at 6:47
                    NSLog doesn't works with Extensions. If you want to debug your extension code, attach pid to your app and you can test it with the help of breakpoints in Extension too.
    – manishsharma93
                    May 28, 2018 at 7:12
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.