在開始之前,首先了解下自定義消息和通知的幾點區別。
自定義消息和通知的區別
- 收到推送自定義消息時推送通知欄不顯示
- 自定義消息推送不經過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特性和過期更新。 - 在極光官網最下方有技術交流群,可以加群找技術咨詢解決。