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 著做權歸做者全部,轉載請聯繫做者得到受權,並標註「簡書做者」。
相關文章
相關標籤/搜索