在 iOS 10 中使用远程通知(富媒体推送通知)在通知栏中显示图像

Posted

技术标签:

【中文标题】在 iOS 10 中使用远程通知(富媒体推送通知)在通知栏中显示图像【英文标题】:Display image in notification bar with remote notification(Rich media push notification) in iOS 10 【发布时间】:2017-01-25 07:38:12 【问题描述】:

我已集成 APNS,并希望在远程通知中显示图像,如下所示;

我使用下面的代码参考link;

AppDelegate.h

#import <UserNotifications/UserNotifications.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate,UNUserNotificationCenterDelegate>

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
     [self registerForRemoteNotification];
     UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
     UIViewController *vc1 = [storyboard instantiateViewControllerWithIdentifier:@"mainscreen"];
     self.window.rootViewController = vc1;
     return YES;


- (void)registerForRemoteNotification 

        if(SYSTEM_VERSION_GRATERTHAN_OR_EQUALTO(@"10.0")) 
            UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
            center.delegate = self;
            [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error)

                 [[UIApplication sharedApplication] registerForRemoteNotifications];
            ];
        
        else 
            [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
            [[UIApplication sharedApplication] registerForRemoteNotifications];
        


- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

            DeviceToken = [[NSString alloc]initWithFormat:@"%@",[[[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""]];
            NSLog(@"Device Token = %@",DeviceToken);
    

然后,我使用 UNNotificationServiceExtension 创建了新目标并创建了新的捆绑包 id "com.RichPush.app.Service-Extension" ,我还使用上述捆绑包为 UNNotificationServiceExtension 创建了新证书和配置文件.

NotificationService.h

#import <UserNotifications/UserNotifications.h>
@interface NotificationService : UNNotificationServiceExtension
@end

NotificationService.m

#import "NotificationService.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];

    // Modify the notification content here...
    //self.bestAttemptContent.body = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.body];

    // check for media attachment, example here uses custom payload keys mediaUrl and mediaType
    NSDictionary *userInfo = request.content.userInfo;
    if (userInfo == nil) 
        [self contentComplete];
        return;
    

    NSString *mediaUrl = userInfo[@"mediaUrl"];
    NSString *mediaType = userInfo[@"mediaType"];

    if (mediaUrl == nil || mediaType == nil) 
        [self contentComplete];
        return;
    

    // load the attachment
    [self loadAttachmentForUrlString:mediaUrl
                            withType:mediaType
                   completionHandler:^(UNNotificationAttachment *attachment) 
                       if (attachment) 
                           self.bestAttemptContent.attachments = [NSArray arrayWithObject:attachment];
                       
                       [self contentComplete];
                   ];



- (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 
    self.contentHandler(self.bestAttemptContent);


- (NSString *)fileExtensionForMediaType:(NSString *)type 
    NSString *ext = type;

    if ([type isEqualToString:@"image"]) 
        ext = @"jpg";
    
   return [@"." stringByAppendingString:ext];


- (void)loadAttachmentForUrlString:(NSString *)urlString withType:(NSString *)type completionHandler:(void(^)(UNNotificationAttachment *))completionHandler  

    __block UNNotificationAttachment *attachment = nil;
    NSURL *attachmentURL = [NSURL URLWithString:urlString];
    NSString *fileExt = [self fileExtensionForMediaType:type];

    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:fileExt]];
                        [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];

@end

我使用下面的 plist 进行服务扩展:

我的播放量是;

    
    "aps": 
        "alert": 
            "title": "title",
            "body": "Your message Here",
            "mutable-content": "1",
            "category": "myNotificationCategory"
        
    ,
    "mediaUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/FloorGoban.JPG/1024px-FloorGoban.jpg",
    "mediaType": "image"
 

请让我知道我错在哪里。

提前致谢。

【问题讨论】:

【参考方案1】:

您需要将 "mutable-content": "1", 标志放在有效负载中的 "alert" 对象之外。

【讨论】:

【参考方案2】:

你这里有一个错误:

然后,我使用 UNNotificationServiceExtension 创建了新目标并创建了新的捆绑包 id "com.RichPush.app.Service-Extension" ,我还使用上述捆绑包为 UNNotificationServiceExtension 创建了新证书和配置文件。

使用 UNNotificationContentExtension 而不是 UNNotificationServiceExtension

创建新target后,xcode会创建swift(obj-c)文件和storyboard界面

我有一个关于 swift 代码的简单示例,它加载图像并显示在大型推送通知视图中

class NotificationViewController: UIViewController, UNNotificationContentExtension 


//image provided from storyboard
@IBOutlet weak var image: UIImageView!

override func viewDidLoad() 
    super.viewDidLoad()

    // Do any required interface initialization here.


func didReceive(_ notification: UNNotification) 
    let userInfo = notification.request.content.userInfo
    // get image url 
   // and load image here  
 

来自苹果文档:

UNNotificationServiceExtension 在发送给用户之前修改远程通知的内容。

UNNotificationContentExtension 为传递的本地或远程通知提供自定义界面。

【讨论】:

如果您只想在通知中显示图像,则不需要 UNNotificationContentExtension。 UNNotificationContentExtension 用于为 Notification 提供自定义接口(虽然不是预览)。【参考方案3】:

您的通知负载应该是这样的:

   aps =     
        alert =         
            body = Testing;
            title = Dining;
        ;
        badge = 1;
        "content-available" = 1;
        "mutable-content" = 1;
        sound = "Bleep-Sound.wav";
    ;


Content-available 和 mutable-content 应该在警报之外,您还应该添加徽章计数......

【讨论】:

以上是关于在 iOS 10 中使用远程通知(富媒体推送通知)在通知栏中显示图像的主要内容,如果未能解决你的问题,请参考以下文章

通知服务应用程序扩展必须在远程通知中显示媒体?

无法使用 ios 10 中的通知服务扩展在远程通知中附加媒体

如何在 iOS 10 应用程序中将媒体附件添加到我的推送通知?

ios 10推送通知媒体附件随机不起作用

iOS8 - 请求远程推送通知

为啥远程推送通知在 iOS 10 上不起作用?