前言
我們首先要在AppDelegate里面進行iOS的適配,可以參考這篇文章
iOS原生推送(APNS)的實現,
如果已經適配過了請忽略。
程序實現
Xcode打開項目,File-->New-->Target;

然后分別選UNNotificationServiceExtension、UNNotificationContent創建Target;

然后在UNNotificationServiceExtension的- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {}方法中添加下面的代碼;
NSMutableArray *actionMutableArr = [[NSMutableArray alloc] initWithCapacity:1];
UNNotificationAction * actionA =[UNNotificationAction actionWithIdentifier:@"ActionA" title:@"不感興趣" options:UNNotificationActionOptionAuthenticationRequired];
UNNotificationAction * actionB = [UNNotificationAction actionWithIdentifier:@"ActionB" title:@"不感興趣" options:UNNotificationActionOptionDestructive];
UNNotificationAction * actionC = [UNNotificationAction actionWithIdentifier:@"ActionC" title:@"進去瞅瞅" options:UNNotificationActionOptionForeground];
UNTextInputNotificationAction * actionD = [UNTextInputNotificationAction actionWithIdentifier:@"ActionD" title:@"作出評論" options:UNNotificationActionOptionDestructive textInputButtonTitle:@"send" textInputPlaceholder:@"say some thing"];
[actionMutableArr addObjectsFromArray:@[actionA,actionB,actionC,actionD]];
if (actionMutableArr.count) {
UNNotificationCategory * notficationCategory = [UNNotificationCategory categoryWithIdentifier:@"categoryNoOperationAction" actions:actionMutableArr intentIdentifiers:@[@"ActionA",@"ActionB",@"ActionC",@"ActionD"] options:UNNotificationCategoryOptionCustomDismissAction];
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObject:notficationCategory]];
}
上面的方法是添加推送消息下面的事件(進入應用查看,取消查看,快捷回復)的,如果你的應用不需要可以忽略;
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
self.bestAttemptContent.categoryIdentifier = @"categoryNoOperationAction";
// Modify the notification content here...
// self.bestAttemptContent.title = [NSString stringWithFormat:@"點擊查看更多內容"];
NSDictionary *dict = self.bestAttemptContent.userInfo;
// NSDictionary *notiDict = dict[@"aps"];
NSString *mediaUrl = [NSString stringWithFormat:@"%@",dict[@"media"][@"url"]];
NSLog(@"%@",mediaUrl);
if (!mediaUrl.length) {
self.contentHandler(self.bestAttemptContent);
}
[self loadAttachmentForUrlString:mediaUrl withType:dict[@"media"][@"type"] completionHandle:^(UNNotificationAttachment *attach) {
if (attach) {
self.bestAttemptContent.attachments = [NSArray arrayWithObject:attach];
}
self.contentHandler(self.bestAttemptContent);
}];
//處理視頻,圖片的等多媒體
- (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];
}
- (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];
}
上面的這兩段代碼是當推送消息來了后,我們將mdeia下的url內的文件下載到本地,然后將路徑交給系統,進而實現推送多媒體文件的目的;
這里說一下必須注意的兩個坑、個坑、坑:
1.將UNNotificationServiceExtension中的pilst文件中添加
(1)在Info.plist中添加NSAppTransportSecurity類型Dictionary。
(2)在NSAppTransportSecurity下添加NSAllowsArbitraryLoads類型Boolean,值設為YES
這是因為從iOS9開始蘋果不允許直接http訪問,加上這兩個字段就可以訪問http,如果你不添加,只有你推送https的media文件才能被下載,http則不能被下載;

2.選中工程---> UNNotificationServiceExtension所對應的Target-->Deploy Target設置為iOS10,因為是從iOS10才支持推送多媒體文件,它默認是從當前Xocde支持的最高版本,比如小編的手機版本iOS10.0.2,它默認是iOS 10.2.0.剛開始小編沒有修改,推送死活出不來圖片,只有文字;后台檢查才發現這里是從iOS 10.2.0支持的,心中一萬個草泥馬崩騰而過;

忙活了這么多還是看一下效果吧,我只做了圖片與視頻,聲音應該差別不大。
推送視頻效果圖

推送圖片效果圖

自定義推送的UI
1、在UNNotificationServiceExtension的- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler方法內為self.bestAttemptContent添加categoryIdentifier
self.bestAttemptContent.categoryIdentifier = @"myNotificationCategory";
然后將這個categoryIdentifier粘貼在UNNotificationContent的infoplist內NSExtension-->NSExtensionAttributes-->UNNotificationExtensionCategory的字段內;然后在下面在添加一個字段UNNotificationExtensionDefaultContentHidden設置bool值為YES,這里是隱藏系統的UI;

- 在上面的下載多媒體文件的- (void)loadAttachmentForUrlString:(NSString *)urlStr withType:(NSString *)type completionHandle:(void(^(UNNotificationAttachment *attach))completionHandler;方法內添加
NSMutableDictionary * dict = [self.bestAttemptContent.userInfo mutableCopy];
[dict setObject:[NSData dataWithContentsOfURL:localURL] forKey:@"image"];
self.bestAttemptContent.userInfo = dict;
我這里是將圖片的Data數據放到推送的userInfo里面,然后在自定義UI的UNNotificationContent內獲取這個Date,然后加載UI;
3、 在UNNotificationContent的maininterface.storyboard內部將UI做好,然后在UNNotificationContent的- (void)didReceiveNotification:(UNNotification *)notification ;方法內進行UI加載。

UI運行效果

項目結構圖
iOS原生推送(APNS)進階iOS10推送圖片、視頻、音樂
注:本文著作權歸作者,由demo大師代發,拒絕轉載,轉載需要作者授權
