在這篇文章,我會給大家講一講更高級一點的,定制化更高的遠程通知。其中會補充我之前沒講的遠程推送(多媒體)通知,以及UNNotificationServiceExtension,UNNotificationContentExtension,UNNotificationAction的相關類。相信大家看了這篇文章,雖不能說對蘋果的遠程推送了如指掌,但是也可以做一些基本的擴展咯~
UNNotificationServiceExtension是iOS10推出後的一個新特性,先看這張圖:
從這張圖上,我們可以看到,原先直接從APNs推送到用戶手機的消息,中間添加了ServiceExtension處理的一個步驟(當然你也可以不處理),通過這個ServiceExtension,我們可以把即將給用戶展示的通知內容,做各種自定義的處理,最終,給用戶呈現一個更為豐富的通知,當然,如果網絡不好,或者附件過大,可能在給定的時間內,我們沒能將通知重新編輯,那麼,則會顯示發過來的原版通知內容。
那麼ServiceExtension可以做什麼呢?它的意義是什麼呢?我總結了幾點:
1、 安全
安全總是擺在第一位的,從iOS9開始,蘋果鼓勵我們使用更為安全的https協議可以看的出來,蘋果公司是對安全很重視的一家公司,為什麼在這裡我會提到安全呢?是因為之前我們的推送內容,不管是通過第三方,還是通過蘋果自帶的通知處理,如果讓有心人對數據做一次攔截,抓個包啥的,我們推送的內容就會完全暴露,當然有的同學說,我可以加密啊~但是不知道大家有沒有想過,如果數據加密,那通知欄會怎麼展示呢?(你千萬別跟我說你把所有的遠程推送變成本地通知。。)通過此次這次增加的UNNotificationServiceExtension的類,便可以更好的幫助我們實現數據的加密。
它的原理便是在收到通知後的最多30s內,你可以把你的通知內容,解密後,在重新展示在用戶的通知攔上。
2、 內容的豐富
之前的通知展示內容比較少,以至於被各種廣告提醒占據了。這次蘋果新添加的附件通知,結合上通知拓展類,便可以給用戶展現出一個有著豐富內容的通知。比如,一個小短片的某一秒的畫面啊(這裡要強烈鄙視各大平台的某些電影預覽圖),又或者是配上一些小圖片啊(通過服務器傳來的imaUrl)等方式來吸引用戶,誘導用戶點開你的通知,促使用戶會使用你的App。其實推送這個功能,雖然有的人會關閉,但是大部分的人還是開啟的,所以說推送這個市場還是很大的喲~靈活利用推送,會讓你的程序擁有無限的可能。
首先,我們不能通過創建UNNotificationServiceExtension的類來使用服務擴展,我們應當創建一個Target,這個Target自帶一個模板,其中有2個方法是系統會自己調用的,如下:
// 你需要通過重寫這個方法,來重寫你的通知內容,也可以在這裡下載附件內容 - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent *contentToDeliver))contentHandler; // 如果處理時間太長,等不及處理了,就會把收到的apns直接展示出來 - (void)serviceExtensionTimeWillExpire;
開始跟著我創建一個UNNotificationServiceExtension吧。
新建Target
選擇如圖所示:
然後寫名字,下一步,即可
此時我們的目錄結構裡面,已經多出了一個文件夾了。
都多了一個myTest。
注意看上圖,這裡的bundleID是你的工程名字的bundleID加上.名稱。
不要修改,系統創建的時候就創建好了,不過我還是給大家說一下這個格式
如果你的工程的BundleID是coderxu.pushDemo,則這個擴展的BundleID就是coderxu.pushDemo.mytest,最後的後綴,是看咱們創建服務擴展時候的名字。其他的小細節,大家可以看看。
到這一步,我們就新建了一個服務通知類的擴展。
在使用這個類的時候,我重寫了以下代碼,大家可以先看下:
(1). 這是處理通知內容重寫的方法:
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; // copy發來的通知,開始做一些處理 self.bestAttemptContent = [request.content mutableCopy]; // Modify the notification content here... self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title]; // 重寫一些東西 self.bestAttemptContent.title = @"我是標題"; self.bestAttemptContent.subtitle = @"我是子標題"; self.bestAttemptContent.body = @"來自徐不同"; // 附件 NSDictionary *dict = self.bestAttemptContent.userInfo; NSDictionary *notiDict = dict[@"aps"]; NSString *imgUrl = [NSString stringWithFormat:@"%@",notiDict[@"imageAbsoluteString"]]; if (!imgUrl.length) { self.contentHandler(self.bestAttemptContent); } [self loadAttachmentForUrlString:imgUrl withType:@"png" completionHandle:^(UNNotificationAttachment *attach) { if (attach) { self.bestAttemptContent.attachments = [NSArray arrayWithObject:attach]; } self.contentHandler(self.bestAttemptContent); }]; }
(2). 這是下載附件通知的方法:
- (void)loadAttachmentForUrlString:(NSString *)urlStr withType:(NSString *)type completionHandle:(void(^)(UNNotificationAttachment *attach))completionHandler{ __block UNNotificationAttachment *attachment = nil; NSURL *attachmentURL = [NSURL URLWithString:urlStr]; 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]; }
(3)判斷文件類型的方法
- (NSString *)fileExtensionForMediaType:(NSString *)type { NSString *ext = type; if ([type isEqualToString:@"image"]) { ext = @"jpg"; } if ([type isEqualToString:@"video"]) { ext = @"mp4"; } if ([type isEqualToString:@"audio"]) { ext = @"mp3"; } return [@"." stringByAppendingString:ext]; }
第一段代碼主要講通知內容的重組,邏輯就是有附件的url,我就下載,如果沒有url我就直接展示通知。
第二段代碼主要講的是,用系統自帶類,下載圖,存圖,找到filePath,創建通知的附件內容。(創建附件的url,必須是一個文件路徑,也就是說,必須下載下,才能獲取文件路徑,開頭是file://)
第三段的代碼主要講判斷文件的後綴類型,然後前端好處理。這裡我的代碼是寫死了,因為我就測試一張圖。最好的方式是服務器返回的 推送內容中,帶有附件的類型。我的iOS開發 iOS10推送必看(高階1)一文中,有講多媒體附件的類型,以及相關的大小限制。
這裡強烈建議,處理推送內容的時候,讓服務器帶上文件類型。重要的事情說三遍
這裡強烈建議,處理推送內容的時候,讓服務器帶上文件類型。重要的事情說三遍
這裡強烈建議,處理推送內容的時候,讓服務器帶上文件類型。重要的事情說三遍
在補充一些問題
1.在這個推送服務的擴展類中,為什麼我使用了系統自帶類下載,沒有使用AFN?以下是一些錯誤的截圖:(可以不看)
選擇你的程序Target
這個時候,大家在打斷點,就可以啦~
最後,在附上推送的內容格式。
推送內容格式如下:
{ "aps": { "alert": "This is some fancy message.", "badge": 1, "sound": "default", "mutable-content": "1", "imageAbsoluteString": "http://upload.univs.cn/2012/0104/1325645511371.jpg" } }
這裡我們要注意一定要有"mutable-content": "1",以及一定要有Alert的字段,否則可能會攔截通知失敗。(蘋果文檔說的)。除此之外,我們還可以添加自定義字段,比如,圖片地址,圖片類型,大家慢慢摸索下吧~有問題可以留言喲~
這一章的最後,附上成功推送的展示圖:
稍後補充以下內容~
# 2、UNNotificationContentExtension ## 2.1、UNNotificationContentExtension簡介 ## 2.2、如何新建一個UNNotificationContentExtension ## 2.3、如何使用以及相關Demo # 3、UNNotificationAction ## 3.1、UNNotificationAction簡介 ## 3.2、如何新建一個UNNotificationAction ## 3.3、如何使用以及相關Demo
如果你喜歡我的文章,不要忘記關注我,謝謝大家了~
另外如果你要轉載,希望可以注明出處,我會寫出更多更好的文章,來回饋大家~
重要的事情說三遍,demo地址
重要的事情說三遍,demo地址
重要的事情說三遍,demo地址