iOS 10 來點不同的推送

簡介

iOS 10 中新增的通知服務擴展功能,在推送通知展現到界面以前提供開發者能夠在後臺對推送的內容進行修改
經過這個修改主要能夠實現如下的幾個需求:javascript

  • 若是推送的內容加密的,能夠在客戶端進行解密。
  • 能夠下載圖片,音樂,視頻,實現多媒體推送的效果。
  • 能夠修改推送的內容,body ,titile ,subtitle 等。(這裏能夠用來實現一些定製化的需求,服務端統一推送,各自修改)
  • 能夠修改本身增長的 userinfo 的 dictionary。

說白了就是在收到蘋果推送的時候,會觸發你的
這是官方給出的注意點:java

  • 1.Include the mutable-content key with a value of 1.
    必定要有 mutable-content 這個字段而且值爲 1,否則是不會執行你的 extsion 的。git

    我測試了改成0,或者不加這個字段並不會執行本地的修改github

  • 2.Include an alert dictionary with subkeys for the title and body of the alert.
    要有一個 alert 的 dictionary 包含 title 和 body 的鍵值。後端

    若是沒有 alert 的話,默認會當作一個 slient notification 服務器

Let's Start !

這裏主要分爲兩種實現方式:本地和遠程。其實無論本地推送仍是遠程推送,對 app 自己實際上是一致的。
主要講一下遠程的實現方式,由於這個的實際運用性更強一點,不過因爲涉及到推送證書的緣故在 demo 中可能很差體現,最後我會給出本地推送的 demo 供你們測試。網絡

基礎推送實現

這裏我就不展開了,要運用修改推送的功能前提是你的 app 要已經有了推送能力。
主要如下幾個注意點:app

  • 在 developer center 申請證書
  • 在 application 中申請推送的權限
  • 拿到 device Token 交給服務器的兄弟

這裏推薦用 SmartPush 來本地測試本地推送,文章最後會介紹。
當服務端已經能愉快的給你推送的消息的時候,咱們開始下一步。ide

新建 extison

對 notification 的修改是做爲一個 extison 的存在,並非在你的 app 的 target 中增長一個 class 的事情,而是新建了一個 target。工具

  • 選中 File -> New -> Target
  • 選擇 Notification Service Extension
  • 選擇名字和相關信息

Xcode 會自動幫你配置好一切,而後會生成一個

NotificationService 的類
會幫你實現兩個方法

  • (void)didReceiveNotificationRequest:(UNNotificationRequest )request withContentHandler:(void (^)(UNNotificationContent _Nonnull))contentHandler

    收到推送時會觸發的方法,給你一個 block 用來回調最終修改後的 Notification

  • (void)serviceExtensionTimeWillExpire

    這個是此次 Service 運行時間到期時候的給你最後的通知(基礎 後臺拉取服務,一般的時間上限是 30s),至關是最後通牒,若你上面的下載操做還沒完成,系統會最後詢問你一次是否是要對內容修改,這裏是你超時狀況下最後的處理機會。

代碼實現

這裏就直接貼代碼吧,其實內容很簡單,具體的流程會在註釋中說明:
這裏用了簡單的一個 DownloadTask 來實現下載,其實若是是大文件或者多資源的話能夠好好利用這個 30 秒進行下載。

#import "NotificationService.h"

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@property (nonatomic,strong) NSURLSessionDownloadTask *downLoadTask;//下載的task 用於取消

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {

    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];

    // Modify the notification content here...
    // self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title];

    //以上代碼均有系統自動生成

    //獲取下載的資源地址 這裏和服務端約定好便可
    NSString *url = request.content.userInfo[@"attach"];
    NSURL *nsurl = [NSURL URLWithString:url];

    //開始下載
    self.downLoadTask = [[NSURLSession sharedSession] downloadTaskWithURL:nsurl completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        if (!error) {

        //將下載後的文件進行 移動到沙盒 切記這裏的文件要及時清理    
            NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
            [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:nil];

        //爲 Notification 增長 attachment
            UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"attachment" URL:[NSURL fileURLWithPath:path] options:nil error:nil];


            self.bestAttemptContent.attachments = @[attachment];
        }

        //無論成功失敗 返回結果
        self.contentHandler(self.bestAttemptContent);

    }];

    [self.downLoadTask resume];
}

- (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.
    NSLog(@"cancel ");
    //取消下載
    [self.downLoadTask cancel];
    self.contentHandler(self.bestAttemptContent);
}

@end複製代碼

Debug

我本身測試的時候,發現直接運行時無法 debug ,根本進不了 service 的斷點,研究了一下才發現了他的 debug 方式。

首先選中目標 service 的 target,強調一下是 service 的 target


而後 build ,XCode 會提示讓你選擇對應的應用

而後就退到後臺進行推送,這時候就能進到這個斷點中了。

這裏要強烈介紹一下這個 Mac 端的工具 !!!炒雞好用!!
Push 的工具推薦用 SmartPush 一個開源的 Mac 端push工具
github.com/shaojiankui…
這個東西是神器!今後不用在和後端糾結證書的問題,我本身測試發送消息沒問題以後就能夠交給後臺了,個人鍋?不存在的!
具體界面是這樣的,可以自動讀取你本地的證書,填個 device token 就能推送了。

Fire!

下面是我所測試的各類類型的效果圖和對應的 payload 你們能夠參考一下

圖片推送

{
    "aps": {
        "alert": {
            "body": "多媒體推送", 
            "title": "我是圖片", 
            "subtitle": "子標題"
        }, 
        "badge": 6, 
        "sound": "default", 
        "category": "Helllo", 
        "mutable-content": 1
    }, 
    "attach": "https://raw.githubusercontent.com/Danny1451/BlogPic/master/face/8.jpg"
}複製代碼

效果大概是這樣


點擊以後是這樣 一個耿直的微笑

mp3 文件

{
    "aps": {
        "alert": {
            "body": "多媒體推送", 
            "title": "我是音樂", 
            "subtitle": "子標題"
        }, 
        "badge": 6, 
        "sound": "default", 
        "category": "Helllo", 
        "mutable-content": 1
    }, 
    "attach": "https://raw.githubusercontent.com/Danny1451/BlogPic/master/pushtest/a.mp3"
}複製代碼

點擊以後是這樣:


MP4 文件

{
    "aps": {
        "alert": {
            "body": "多媒體推送", 
            "title": "我是視頻", 
            "subtitle": "子標題"
        }, 
        "badge": 6, 
        "sound": "default", 
        "category": "Helllo", 
        "mutable-content": 1
    }, 
    "attach": "https://raw.githubusercontent.com/Danny1451/BlogPic/master/pushtest/video.mp4"
}複製代碼

點擊以前就和音樂消息是同樣的
以後是這樣的

最後

注意點

  • 注意文件下載的位置的存儲管理,及時的清空。
  • 注意若是要用第三方的庫的話,extison 要單獨引用和編譯一份,由於和 app 同樣他們實際上是獨立進程的。
  • 注意戶的網絡狀況,進行判斷是否要下載資源,否則用戶的流量就給你這麼咔咔咔全耗完了。

Demo地址:
實現了 Local 的推送方式,將 extison 也加進去了,可是因爲須要證書的緣故沒有加到 target 中,代碼能夠參考。

github.com/Danny1451/P… (若是感到有用的加個✨吧 溜了 溜了)

若是想要我手機壁紙的話 請留言 哈哈哈哈 (跑

相關文章
相關標籤/搜索