ios10 推送富文本消息

 

注意!!!html

Media Attachments和自定义推送界面

本地推送和远程推送同时均可支持附带Media Attachments。不过远程通知须要实现通知服务扩展UNNotificationServiceExtension,在service extension里面去下载attachment,可是须要注意,service extension会限制下载的时间(30s),而且下载的文件大小也会一样被限制。这里毕竟是一个推送,而不是把全部的内容都推送给用户。因此你应该去推送一些缩小比例以后的版本。好比图片,推送里面附带缩略图,当用户打开app以后,再去下载完整的高清图。视频就附带视频的关键帧或者开头的几秒,当用户打开app以后再去下载完整视频。json

attachment支持图片,音频,视频,附件支持的类型及大小网络


附件类型和大小.png

系统会在通知注册前校验附件,若是附件出问题,通知注册失败;校验成功后,附件会转入attachment data store;若是附件是在app bundle,则是会被copy来取代move
media attachments能够利用3d touch进行预览和操做
attachment data store的位置?利用代码测试 获取在磁盘上的图片文件做为attachment,会发现注册完通知后,图片文件被移除,在app的沙盒中找不到该文件在哪里; 想要获取已存在的附件内容,文档中说起能够经过UNUserNotificationCenter中方法,但目前文档中这2个方法仍是灰的,见苹果开发者文档app


Apple developer.png
//就是这两个方法 getDataForAttachment:withCompletionHandler: getReadFileHandleForAttachment:withCompletionHandler:

 

 

一、准备工做
附件限定https协议,因此咱们如今找一个支持https的图床用来测试,我以前能测试的图床如今不能用了。大家能够自行googole,这是我以前上传的图片连接:https://p1.bpimg.com/524586/475bc82ff016054ds.jpg
具体附件格式能够查看苹果开发文档 less

二、添加新的Targe--> Notification Service
先在Xcode 打开你的工程,File-->New-->Targe而后添加这个Notification Service:ide


Notification Service.png

这样在你工程里能看到下面目录:函数


Notification Service.png


而后会自动建立一个 UNNotificationServiceExtension 的子类 NotificationService,经过完善这个子类,来实现你的需求。布局

点开 NotificationService.m 会看到 2 个方法:测试

// Call contentHandler with the modified notification content to deliver. If the handler is not called before the service's time expires then the unmodified notification will be delivered. // You are expected to override this method to implement push notification modification. - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *contentToDeliver))contentHandler; // Will be called just before this extension is terminated by the system. You may choose whether to override this method. - (void)serviceExtensionTimeWillExpire;

didReceiveNotificationRequest让你能够在后台处理接收到的推送,传递最终的内容给 contentHandler
serviceExtensionTimeWillExpire 在你得到的一小段运行代码的时间即将结束的时候,若是仍然没有成功的传入内容,会走到这个方法,能够在这里传确定不会出错的内容,或者他会默认传递原始的推送内容ui

主要的思路就是在这里把附件下载下来,而后才能展现渲染,下面是下载保存的相关方法:

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; NSString * attchUrl = [request.content.userInfo objectForKey:@"image"]; //下载图片,放到本地 UIImage * imageFromUrl = [self getImageFromURL:attchUrl]; //获取documents目录 NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString * documentsDirectoryPath = [paths firstObject]; NSString * localPath = [self saveImage:imageFromUrl withFileName:@"MyImage" ofType:@"png" inDirectory:documentsDirectoryPath]; if (localPath && ![localPath isEqualToString:@""]) { UNNotificationAttachment * attachment = [UNNotificationAttachment attachmentWithIdentifier:@"photo" URL:[NSURL URLWithString:[@"file://" stringByAppendingString:localPath]] options:nil error:nil]; if (attachment) { self.bestAttemptContent.attachments = @[attachment]; } } self.contentHandler(self.bestAttemptContent); } - (UIImage *) getImageFromURL:(NSString *)fileURL { NSLog(@"执行图片下载函数"); UIImage * result; //dataWithContentsOfURL方法须要https链接 NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]]; result = [UIImage imageWithData:data]; return result; } //将所下载的图片保存到本地 - (NSString *) saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath { NSString *urlStr = @""; if ([[extension lowercaseString] isEqualToString:@"png"]){ urlStr = [directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]]; [UIImagePNGRepresentation(image) writeToFile:urlStr options:NSAtomicWrite error:nil]; } else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"]){ urlStr = [directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]]; [UIImageJPEGRepresentation(image, 1.0) writeToFile:urlStr options:NSAtomicWrite error:nil]; } else{ NSLog(@"extension error"); } return urlStr; } - (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); }

apes以下:

{
   "aps":{ "alert" : { "title" : "iOS远程消息,我是主标题!-title", "subtitle" : "iOS远程消息,我是主标题!-Subtitle", "body" : "Dely,why am i so handsome -body" }, "sound" : "default", "badge" : "1", "mutable-content" : "1", "category" : "Dely_category" }, "image" : "https://p1.bpimg.com/524586/475bc82ff016054ds.jpg", "type" : "scene", "id" : "1007" }

注意:mutable-content这个键值为1,这意味着此条推送能够被 Service Extension 进行更改,也就是说要用Service Extension须要加上这个键值为1.

三、添加新的Targe--> Notification Content

先在Xcode 打开你的工程,File-->New-->Targe而后添加这个 Notification Content:


Notification Content.png

这样你在工程里一样看到下面的目录:


Notification Content.png

点开 NotificationViewController.m 会看到 2 个方法:

- (void)viewDidLoad; - (void)didReceiveNotification:(UNNotification *)notification;

前者渲染UI,后者获取通知信息,更新UI控件中的数据。

在MainInterface.storyboard中自定你的UI页面,能够随意发挥,可是这个UI见面只能用于展现,并不能响应点击或者手势其余事件,只能经过category来实现,下面本身添加view和约束


MainInterface.storyboard.png

而后把view拉到.m文件中,代码以下:

#import "NotificationViewController.h" #import <UserNotifications/UserNotifications.h> #import <UserNotificationsUI/UserNotificationsUI.h> @interface NotificationViewController () <UNNotificationContentExtension> @property IBOutlet UILabel *label; @property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @implementation NotificationViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any required interface initialization here. // UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; // [self.view addSubview:view]; // view.backgroundColor = [UIColor redColor]; } - (void)didReceiveNotification:(UNNotification *)notification { self.label.text = notification.request.content.body; UNNotificationContent * content = notification.request.content; UNNotificationAttachment * attachment = content.attachments.firstObject; if (attachment.URL.startAccessingSecurityScopedResource) { self.imageView.image = [UIImage imageWithContentsOfFile:attachment.URL.path]; } } @end

有人要有疑问了,可不能够不用storyboard来自定义界面?固然能够了!
只须要在Notifications Content 的info.plist中把NSExtensionMainStoryboard替换为NSExtensionPrincipalClass,而且value对应你的类名!
而后在viewDidLoad里用纯代码布局就能够了


纯代码自定义通知界面.png

四、发送推送

完成上面的工做的时候基本上能够了!而后运行工程,
上面的json数据放到APNS Pusher里面点击send:


68BFC911-791F-410D-8849-1F06A135B04E.png

稍等片刻应该能收到消息:


远端消息.jpg

长按或者右滑查看:


远端消息2.jpg

注意 注意 注意:
若是你添加了category,须要在Notification content的info.plist添加一个键值对UNNotificationExtensionCategory的value值和category Action的category值保持一致就行。


UNNotificationExtensionCategory.png

同时在推送json中添加category键值对也要和上面两个地方保持一致:


pusher.png

就变成了下面:


远端消息3.jpg

上面介绍了远端须要Service Extension 的远端推送
iOS 10附件通知(图片、gif、音频、视频)。不过对图片和视频的大小作了一些限制(图片不能超过 10M,视频不能超过 50M),并且附件资源必须存在本地,若是是远程推送的网络资源须要提早下载到本地。
若是是本地的就简单了只须要在Service Extension的NotificationService.m的- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler拿到资源添加到Notification Content,在Notification Content的控制器取到资源本身来作需求处理和展现

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; // 资源路径 NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"video" withExtension:@"mp4"]; // 建立附件资源 // * identifier 资源标识符 // * URL 资源路径 // * options 资源可选操做 好比隐藏缩略图之类的 // * error 异常处理 UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"video.attachment" URL:videoURL options:nil error:nil]; // 将附件资源添加到 UNMutableNotificationContent 中 if (attachment) { self.bestAttemptContent.attachments = @[attachment]; } self.contentHandler(self.bestAttemptContent); }

Notification.png

上图若是你想把default 隐藏掉,只须要在Notification Content 的info.plist中添加一个键值UNNotificationExtensionDefaultContentHidden设置为YES就能够了:

 

hiddenDefaultContent.png
 
 
 
 
转自/Dely(简书做者) 原文连接:http://www.jianshu.com/p/81c6bd16c7ac 著做权归做者全部,转载请联系做者得到受权,并标注“简书做者”。
相关文章
相关标签/搜索