http://www.cocoachina.com/ios/20161017/17769.html
如果大家還沒有看我的這兩篇文章,建議還是先閱讀一下,循序漸進么~文章鏈接如下:
iOS開發 iOS10推送必看(基礎篇)
iOS開發 iOS10推送必看(高階1)
這次的最后,終於有demo咯~
在這篇文章,我會給大家講一講更高級一點的,定制化更高的遠程通知。其中會補充我之前沒講的遠程推送(多媒體)通知,以及UNNotificationServiceExtension,UNNotificationContentExtension,UNNotificationAction的相關類。相信大家看了這篇文章,雖不能說對蘋果的遠程推送了如指掌,但是也可以做一些基本的擴展咯~
1、UNNotificationServiceExtension
1.1 UNNotificationServiceExtension簡介
UNNotificationServiceExtension是iOS10推出后的一個新特性,先看這張圖:
從這張圖上,我們可以看到,原先直接從APNs推送到用戶手機的消息,中間添加了ServiceExtension處理的一個步驟(當然你也可以不處理),通過這個ServiceExtension,我們可以把即將給用戶展示的通知內容,做各種自定義的處理,最終,給用戶呈現一個更為豐富的通知,當然,如果網絡不好,或者附件過大,可能在給定的時間內,我們沒能將通知重新編輯,那么,則會顯示發過來的原版通知內容。
那么ServiceExtension可以做什么呢?它的意義是什么呢?我總結了幾點:
-
1、安全
安全總是擺在第一位的,從iOS9開始,蘋果鼓勵我們使用更為安全的https協議可以看的出來,蘋果公司是對安全很重視的一家公司,為什么在這里我會提到安全呢?是因為之前我們的推送內容,不管是通過第三方,還是通過蘋果自帶的通知處理,如果讓有心人對數據做一次攔截,抓個包啥的,我們推送的內容就會完全暴露,當然有的同學說,我可以加密啊~但是不知道大家有沒有想過,如果數據加密,那通知欄會怎么展示呢?(你千萬別跟我說你把所有的遠程推送變成本地通知。。)通過此次這次增加的UNNotificationServiceExtension的類,便可以更好的幫助我們實現數據的加密。
它的原理便是在收到通知后的最多30s內,你可以把你的通知內容,解密后,在重新展示在用戶的通知攔上。 -
2、內容的豐富
之前的通知展示內容比較少,以至於被各種廣告提醒占據了。這次蘋果新添加的附件通知,結合上通知拓展類,便可以給用戶展現出一個有着豐富內容的通知。比如,一個小短片的某一秒的畫面啊(這里要強烈鄙視各大平台的某些電影預覽圖),又或者是配上一些小圖片啊(通過服務器傳來的imaUrl)等方式來吸引用戶,誘導用戶點開你的通知,促使用戶會使用你的App。其實推送這個功能,雖然有的人會關閉,但是大部分的人還是開啟的,所以說推送這個市場還是很大的喲~靈活利用推送,會讓你的程序擁有無限的可能。
1.2、如何新建一個UNNotificationServiceExtension
首先,我們不能通過創建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.3、如何使用以及相關Demo
在使用這個類的時候,我重寫了以下代碼,大家可以先看下:
(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). 這是下載附件通知的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
- (
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)判斷文件類型的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
|
- (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?
答:不知道為什么,導入AFN后總是出現各種編譯報錯啊。主要涉及這幾個情況
1.用cocoapods導入AFN,在類引入AFN,編譯報錯!!
2.手動拖拽AFN進工程(不勾選),在類引入AFN,編譯報錯!!
3.手動拖拽AFN進工程(勾選),直接編譯報錯!!
4.下載用通知回調的方式(慢,線程不確定)
最后我就選擇這個block回調,系統類下載的方式,來下載通知中的附件。
以下是一些錯誤的截圖:(可以不看)
-
2.如果調試這個通知擴展類,為什么我跑程序的時候,打斷點無反應?
答:這是因為你跑的target不對,正確的做法是,跑正確的target,具體如下圖: -
選擇你的程序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
如果你喜歡我的文章,不要忘記關注我,謝謝大家了~
另外如果你要轉載,希望可以注明出處,我會寫出更多更好的文章,來回饋大家~