在開始之前窘问,首先了解下自定義消息和通知的幾點區(qū)別。
自定義消息和通知的區(qū)別
- 收到推送自定義消息時推送通知欄不顯示
- 自定義消息推送不經(jīng)過APNS宜咒,所以說跟推送證書沒有關(guān)系
- 只有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
}
通知(極光遠程推送)
調(diào)用此 API 來取得應用程序?qū)?RegistrationID。 只有當應用程序成功注冊到 JPush 的服務器時才返回對應的值故黑,否則返回空字符串儿咱。
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
JPUSHService.registerDeviceToken(deviceToken)
/**
completionHandler用于處理設(shè)置返回結(jié)果
resCode返回的結(jié)果狀態(tài)碼
registrationID返回registrationID
*/
JPUSHService.registrationIDCompletionHandler { (resCode, registrationID) in
print("resCode--", resCode, " registrationID---", registrationID ?? "沒有")
}
}
注冊失敗回調(diào)方法
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("didFailToRegisterForRemoteNotificationsWithError----", error)
}
iOS10以下的系統(tǒng)版本庭砍,收到本地通知(LocalNotification)時調(diào)用
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
let userInfo = notification.userInfo;
print("userInfo-------", userInfo ?? ["":""])
}
基于iOS10以下iOS 7 及以上的系統(tǒng)版本,收到遠程通知(RemoteNotification)時調(diào)用
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及以上系統(tǒng)版本,app在后臺(1咆槽、app在后臺運行 2、鎖屏狀態(tài) 3、app關(guān)閉時)收到通知并且當用戶點擊通知欄上的消息時調(diào)用
@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() // 系統(tǒng)要求執(zhí)行這個方法
}
iOS10及以上系統(tǒng)版本,app處于前臺時接收到通知時調(diào)用
@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)) // 需要執(zhí)行這個方法方面,選擇是否提醒用戶,有Badge、Sound扬蕊、Alert三種類型可以選擇設(shè)置
}
自定義方法再愈,用于收到遠程通知后的一些處理操作,比如取值以及頁面的跳轉(zhuǎn)等等
func handleTheRemoteNotification(userInfo: NSDictionary) {
let aps = userInfo["aps"] as? NSDictionary // 取得 APNs 標準信息內(nèi)容
let content = aps?["alert"] as? String ?? "" // 推送顯示的內(nèi)容
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
// 所需業(yè)務邏輯處理菩佑。劣光。雄可。
}
let cancelAction = UIAlertAction(title: "取消", style: .default) { (action) in
UIApplication.shared.applicationIconBadgeNumber -= 1
// 不作處理
}
ctrlAlert.addAction(cancelAction)
ctrlAlert.addAction(confirmAction)
let rootVC = UIApplication.shared.keyWindow?.rootViewController
}
通知(本地推送)
對于一些業(yè)務需求箱残,比如鬧鈴或者日歷的一些提醒事件等,自己推送消息俄删,實現(xiàn)推送通知的效果妨猩。
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服務器獲取用戶推送的自定義消息內(nèi)容和標題以及附加字段等迈勋。
這些內(nèi)容是和后臺的同學們協(xié)商好的较鼓,并且由他們來寫好向極光推送的相應服務谆级。
獲取iOS的推送內(nèi)容需要在appDelegate類中注冊通知并實現(xiàn)回調(diào)方法吕朵。
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
}
回調(diào)方法
// 接收自定義消息
func networkDidReceiveMessage(notification:NSNotification) {
let userInfo: NSDictionary = notification.userInfo! as NSDictionary
print("自定義消息---",userInfo)
// 業(yè)務邏輯處理。板惑。喷好。
}
標簽與別名
別名 alias
為安裝了應用程序的用戶订雾,取個別名來標識识补。以后給該用戶 Push 消息時孕荠,就可以用此別名來指定。
每個用戶只能指定一個別名骚灸。
同一個應用程序內(nèi)雏赦,對不同的用戶靴寂,建議取不同的別名榨汤。這樣蜜宪,盡可能根據(jù)別名來唯一確定用戶缝呕。
系統(tǒng)不限定一個別名只能指定一個用戶。如果一個別名被指定到了多個用戶煎源,當給指定這個別名發(fā)消息時,服務器端API會同時給這多個用戶發(fā)送消息耙册。
舉例:在一個用戶要登錄的游戲中毫捣,可能設(shè)置別名為 userid详拙。游戲運營時,發(fā)現(xiàn)該用戶 3 天沒有玩游戲了蔓同,則根據(jù) userid 調(diào)用服務器端API發(fā)通知到客戶端提醒用戶饶辙。
標簽 tag
為安裝了應用程序的用戶,打上標簽斑粱。其目的主要是方便開發(fā)者根據(jù)標簽弃揽,來批量下發(fā) Push 消息。
可為每個用戶打多個標簽则北。
舉例: game, old_page, women
別名與標簽的設(shè)置
因為別名和標簽可以重復設(shè)置矿微,所以我把它放在了登錄方法中。
func login() {
//極光推送 注冊別名
let alias = String(format: "%d", userId)
JPUSHService.setTags(["lowbeer","doubeer"], aliasInbackground: alias)
}
然后在退出登錄時注銷別名和標簽尚揣,避免在多個設(shè)備上登錄后涌矢,通過別名發(fā)送通知時,多個設(shè)備都會收到的情況惑艇。
// 退出登錄
func logout() {
// 注銷推送別名和標簽
JPUSHService.setTags([], aliasInbackground: "")
}
參數(shù)說明
alias
- nil 此次調(diào)用不設(shè)置此值蒿辙。
- 空字符串 ("")表示取消之前的設(shè)置拇泛。
- 每次調(diào)用設(shè)置有效的別名滨巴,覆蓋之前的設(shè)置。
- 有效的別名組成:字母(區(qū)分大小寫)俺叭、數(shù)字恭取、下劃線、漢字熄守,特殊- 字符(v2.1.9支持)@!#$&*+=.|蜈垮。
- 限制:alias 命名長度限制為 40 字節(jié)耗跛。(判斷長度需采用UTF-8編碼)
tags
- nil 此次調(diào)用不設(shè)置此值。
- 空集合([NSSet set])表示取消之前的設(shè)置攒发。
- 集合成員類型要求為String類型
- 每次調(diào)用至少設(shè)置一個 tag调塌,覆蓋之前的設(shè)置,不是新增惠猿。
- 有效的標簽組成:字母(區(qū)分大小寫)羔砾、數(shù)字、下劃線偶妖、漢字姜凄,特殊字符(v2.1.9支持)@!#$&*+=.|。
- 限制:每個 tag 命名長度限制為 40 字節(jié)趾访,最多支持設(shè)置 1000 個 tag态秧,但總長度不得超過7K字節(jié)。(判斷長度需采用UTF-8編碼)
單個設(shè)備最多支持設(shè)置 1000 個 tag扼鞋。App 全局 tag 數(shù)量無限制申鱼。
小結(jié)
在推送測試時如果接收不到通知,不要著急藏鹊,不要悲傷润讥,深呼吸,淡定~~~
- 要檢查好項目的開發(fā)和生產(chǎn)證書是否配置正確盘寡,并上傳到了極光應用后臺楚殿,并保證證書沒有過期。參考SDK集成指南 和 證書設(shè)置指南
- 項目Target的Push Notifications開關(guān)是否打開竿痰。
- 卸載應用重新安裝脆粥。我有次第一次收到了,但是后邊卻無論如何都接收不到了影涉,然后拿著RegId和MsgId問了下極光的技術(shù)变隔,他們告訴我:
1、apple認為token失效了
2蟹倾、蘋果建議程序每次啟動的時候從 apns 獲取 devicetoken
重新獲取一次新的token匣缘,測試時,簡單的操作就是卸載重裝
---該問題可以看下這個蘋果APNs’ device token特性和過期更新鲜棠。 - 在極光官網(wǎng)最下方有技術(shù)交流群肌厨,可以加群找技術(shù)咨詢解決。