Swift JPush極光推送通知和自定義消息

在開始之前,首先了解下自定義消息和通知的幾點區別。

自定義消息和通知的區別

  • 收到推送自定義消息時推送通知欄不顯示
  • 自定義消息推送不經過APNS,所以說跟推送證書沒有關系
  • 只有app在前臺時才能收到自定義消息,未啟動或者啟動但處于后臺時接收不到(解決了不想在app未啟動時收到推送消息的問題)

SDK初始化

Appdelegate文件

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        // 極光推送
        if (UIDevice.current.systemVersion as NSString).floatValue >= 10.0  {
            
            if #available(iOS 10.0, *) {
                let entity = JPUSHRegisterEntity()
                entity.types = NSInteger(UNAuthorizationOptions.alert.rawValue | UNAuthorizationOptions.badge.rawValue | UNAuthorizationOptions.sound.rawValue)
                _ = JPUSHService.register(forRemoteNotificationConfig: entity, delegate: self)
            } else {
                // Fallback on earlier versions
            }
            
        } else if  (UIDevice.current.systemVersion as NSString).floatValue >= 8.0 {
            //可以添加自定義categories
            JPUSHService.register(forRemoteNotificationTypes: UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue | UIUserNotificationType.alert.rawValue, categories: nil)
        } else {
            //categories 必須為nil
            JPUSHService.register(forRemoteNotificationTypes: UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue | UIUserNotificationType.alert.rawValue, categories: nil)
        }
        
        var isJpushProduction: Bool
        #if DEBUG
            isJpushProduction = false
        #else
            isJpushProduction = true
        #endif
        
        JPUSHService.setup(withOption: launchOptions, appKey: JPUSHService_appKey, channel: "Publish channel", apsForProduction: isJpushProduction, advertisingIdentifier: nil)
        
        return true
    }

通知(極光遠程推送)

調用此 API 來取得應用程序對應的 RegistrationID。 只有當應用程序成功注冊到 JPush 的服務器時才返回對應的值,否則返回空字符串。

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        JPUSHService.registerDeviceToken(deviceToken)
        
        /**
         completionHandler用于處理設置返回結果
         resCode返回的結果狀態碼
         registrationID返回registrationID
         */
        JPUSHService.registrationIDCompletionHandler { (resCode, registrationID) in
            print("resCode--", resCode, "    registrationID---", registrationID ?? "沒有")
        }
    }

注冊失敗回調方法

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        
        print("didFailToRegisterForRemoteNotificationsWithError----", error)
    }

iOS10以下的系統版本,收到本地通知(LocalNotification)時調用

func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
        
        let userInfo = notification.userInfo;
        print("userInfo-------", userInfo ?? ["":""])
    }

基于iOS10以下iOS 7 及以上的系統版本,收到遠程通知(RemoteNotification)時調用

private func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        
        JPUSHService.handleRemoteNotification(userInfo)
        // 收到遠程通知后的處理
        handleTheRemoteNotification(userInfo: userInfo as NSDictionary)
        completionHandler(UIBackgroundFetchResult.newData)
    }

在iOS 10出來后,極光推出了下面的兩個新方法來替代了以上的兩個方法。

iOS10及以上系統版本,app在后臺(1、app在后臺運行 2、鎖屏狀態 3、app關閉時)收到通知并且當用戶點擊通知欄上的消息時調用

@available(iOS 10.0, *)
    func jpushNotificationCenter(_ center: UNUserNotificationCenter!, didReceive response: UNNotificationResponse!, withCompletionHandler completionHandler: (() -> Void)!) {
        
        let userInfo = response.notification.request.content.userInfo
        if response.notification.request.trigger?.isKind(of: UNPushNotificationTrigger.classForCoder()) == true {
            
            JPUSHService.handleRemoteNotification(userInfo)
            print("iOS10后臺收到通知(當用戶點擊通知欄的時候)...")
            // 收到遠程通知后的處理
            handleTheRemoteNotification(userInfo: userInfo as NSDictionary)
            
        } else {
            print("----本地通知")
        }
        
        completionHandler() // 系統要求執行這個方法
    }

iOS10及以上系統版本,app處于前臺時接收到通知時調用

@available(iOS 10.0, *)
    func jpushNotificationCenter(_ center: UNUserNotificationCenter!, willPresent notification: UNNotification!, withCompletionHandler completionHandler: ((Int) -> Void)!) {
        
        let userInfo = notification.request.content.userInfo
        
        if notification.request.trigger?.isKind(of: UNPushNotificationTrigger.classForCoder()) == true {
            JPUSHService.handleRemoteNotification(userInfo)
            print("iOS10 前臺收到遠程通知...")
            // 收到遠程通知后的處理
            handleTheRemoteNotification(userInfo: userInfo as NSDictionary)
            
        } else {
            print("本地通知...")
        }
        
        let tempPresentationOptions = UNNotificationPresentationOptions.alert.rawValue |  UNNotificationPresentationOptions.sound.rawValue | UNNotificationPresentationOptions.badge.rawValue
        completionHandler(Int(tempPresentationOptions)) // 需要執行這個方法,選擇是否提醒用戶,有Badge、Sound、Alert三種類型可以選擇設置
    }

自定義方法,用于收到遠程通知后的一些處理操作,比如取值以及頁面的跳轉等等

func handleTheRemoteNotification(userInfo: NSDictionary) {
        
        let aps = userInfo["aps"] as? NSDictionary // 取得 APNs 標準信息內容
        let content = aps?["alert"] as? String ?? "" // 推送顯示的內容
        let customizeField = aps?["customizeExtras"] as? String ?? "" // 服務端中Extras字段,key是自己定義的
        
        let ctrlAlert = UIAlertController(title: "提醒", message: content, preferredStyle: UIAlertControllerStyle.alert)
        
        let confirmAction = UIAlertAction(title: "確定", style: .default){ (action) in
            UIApplication.shared.applicationIconBadgeNumber -= 1
            // 所需業務邏輯處理。。。
        }
        let cancelAction =  UIAlertAction(title: "取消", style: .default) { (action) in
            UIApplication.shared.applicationIconBadgeNumber -= 1
            // 不作處理
        }
        
        ctrlAlert.addAction(cancelAction)
        ctrlAlert.addAction(confirmAction)
        
        let rootVC = UIApplication.shared.keyWindow?.rootViewController
}

通知(本地推送)

對于一些業務需求,比如鬧鈴或者日歷的一些提醒事件等,自己推送消息,實現推送通知的效果。

func pushLocalNotification() {
        
        let notification = UILocalNotification()
        if #available(iOS 8.2, *) {
            notification.alertTitle = "小蝸牛"
        } else {
            // Fallback on earlier versions
        }
        notification.alertBody = "快來玩啊~"
        notification.userInfo = ["name": "Tony", "gender": "man"]
        UIApplication.shared.presentLocalNotificationNow(notification)
    }

自定義消息

功能說明:只有在前端運行的時候才能收到自定義消息的推送。
從jpush服務器獲取用戶推送的自定義消息內容和標題以及附加字段等。
這些內容是和后臺的同學們協商好的,并且由他們來寫好向極光推送的相應服務。

獲取iOS的推送內容需要在appDelegate類中注冊通知并實現回調方法。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        // 極光推送,接收自定義消息
        let defaultCenter = NotificationCenter.default
        defaultCenter.addObserver(self, selector: #selector(networkDidReceiveMessage(notification:)), name: NSNotification.Name.jpfNetworkDidReceiveMessage, object: nil)
        
        return true
    }

回調方法

// 接收自定義消息
    func networkDidReceiveMessage(notification:NSNotification) {

        let userInfo: NSDictionary = notification.userInfo! as NSDictionary
        print("自定義消息---",userInfo)
        
        // 業務邏輯處理。。。
    }

標簽與別名

別名 alias

為安裝了應用程序的用戶,取個別名來標識。以后給該用戶 Push 消息時,就可以用此別名來指定。
每個用戶只能指定一個別名。
同一個應用程序內,對不同的用戶,建議取不同的別名。這樣,盡可能根據別名來唯一確定用戶。
系統不限定一個別名只能指定一個用戶。如果一個別名被指定到了多個用戶,當給指定這個別名發消息時,服務器端API會同時給這多個用戶發送消息。
舉例:在一個用戶要登錄的游戲中,可能設置別名為 userid。游戲運營時,發現該用戶 3 天沒有玩游戲了,則根據 userid 調用服務器端API發通知到客戶端提醒用戶。

標簽 tag

為安裝了應用程序的用戶,打上標簽。其目的主要是方便開發者根據標簽,來批量下發 Push 消息。
可為每個用戶打多個標簽。
舉例: game, old_page, women

別名與標簽的設置
因為別名和標簽可以重復設置,所以我把它放在了登錄方法中。

func login() {
  //極光推送 注冊別名
  let alias = String(format: "%d", userId)
  JPUSHService.setTags(["lowbeer","doubeer"], aliasInbackground: alias)
}

然后在退出登錄時注銷別名和標簽,避免在多個設備上登錄后,通過別名發送通知時,多個設備都會收到的情況。

// 退出登錄
func logout() {
  // 注銷推送別名和標簽
  JPUSHService.setTags([], aliasInbackground: "")
}

參數說明

alias
  • nil 此次調用不設置此值。
  • 空字符串 ("")表示取消之前的設置。
  • 每次調用設置有效的別名,覆蓋之前的設置。
  • 有效的別名組成:字母(區分大小寫)、數字、下劃線、漢字,特殊- 字符(v2.1.9支持)@!#$&*+=.|。
  • 限制:alias 命名長度限制為 40 字節。(判斷長度需采用UTF-8編碼)
tags
  • nil 此次調用不設置此值。
  • 空集合([NSSet set])表示取消之前的設置。
  • 集合成員類型要求為String類型
  • 每次調用至少設置一個 tag,覆蓋之前的設置,不是新增。
  • 有效的標簽組成:字母(區分大小寫)、數字、下劃線、漢字,特殊字符(v2.1.9支持)@!#$&*+=.|。
  • 限制:每個 tag 命名長度限制為 40 字節,最多支持設置 1000 個 tag,但總長度不得超過7K字節。(判斷長度需采用UTF-8編碼)
    單個設備最多支持設置 1000 個 tag。App 全局 tag 數量無限制。

小結

在推送測試時如果接收不到通知,不要著急,不要悲傷,深呼吸,淡定~~~

  • 要檢查好項目的開發和生產證書是否配置正確,并上傳到了極光應用后臺,并保證證書沒有過期。參考SDK集成指南證書設置指南
  • 項目Target的Push Notifications開關是否打開。
  • 卸載應用重新安裝。我有次第一次收到了,但是后邊卻無論如何都接收不到了,然后拿著RegId和MsgId問了下極光的技術,他們告訴我:
    1、apple認為token失效了
    2、蘋果建議程序每次啟動的時候從 apns 獲取 devicetoken
    重新獲取一次新的token,測試時,簡單的操作就是卸載重裝
    ---該問題可以看下這個蘋果APNs’ device token特性和過期更新
  • 在極光官網最下方有技術交流群,可以加群找技術咨詢解決。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 版本記錄 前言 前一篇已經對ios新特性進行了介紹,這一篇則對ios的SDK進行說明。1. 極光推送集成(一)2....
    刀客傳奇閱讀 1,346評論 0 1
  • 版本記錄 前言 ??現在很多APP都有推送功能,其中極光推送就是很多APP的首選。我們最近的幾個APP也是用的極光...
    刀客傳奇閱讀 8,537評論 0 8
  • 點擊查看原文 Web SDK 開發手冊 SDK 概述 網易云信 SDK 為 Web 應用提供一個完善的 IM 系統...
    layjoy閱讀 13,950評論 0 15
  • 推送技術產生場景: --服務器端主動性: 客戶端與服務器交互都是客戶端主動的, 服務器一般不能主動與客戶端進行數據...
    原軍鋒閱讀 34,819評論 4 60
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,991評論 19 139