不得不說極光推送有一點做得是很不到位,swift都發布那么久了,官方提供的API盡然沒有提供任何關于swift的API,友盟還象征性的在橋接文件中提一下,不過對于swift開發者都一樣苦惱的進行翻譯,而且翻譯后根據各種報錯修改,去警告,而且我發現極光有的API分散性太厲害,耦合性略高,下面結合代碼給大家講解一下
首先提一下極光推送的兩大部分,APNs 推送(代理),與 JPush 應用內消息。關于兩者的區別我已附圖
經過對比不黑不擂,我感覺還是APNs 通知比較贊,如果按JPush 應用內消息來搞那不和安卓的推送一樣了?iOS那么優勢的推送,豈不浪費了?(安卓機不打開應用一般是收不到推送消息的,這時有的小伙兒可能會疑問了,沒有啊,我這有的app在后臺或者被殺死的也能收到啊?那是因為人家足夠牛逼,和手機廠商談好了合作,有綠色通道啊,哈哈??,期待未來會不一樣啊,若是安卓這邊有大神有獨到的見解或者解決方式,歡迎指點哈!)好的我們繼續
首先我們進行應用的創建以及SDK的集成,這里我就不多說了看了一下極光的文檔這一塊還是不錯的,文檔夠詳細,我們主要談swift的API,附上網址
https://docs.jiguang.cn/jpush/client/iOS/ios_guide_new/
這塊我說一下,有的時候我們打開按鈕的時候下邊的兩個對號會報錯我們command + shift + k 清理一下,在重啟xcode就好了
一起準備就緒我們開始代碼部分:
首先為了能夠吊起oc的API我們需要在橋接文件導入以下代碼,橋接文件不會創建的自行谷歌或者歡迎私信
// 引入JPush功能所需頭文件
#import "JPUSHService.h"
// iOS10注冊APNs所需頭文件
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif
// 如果需要使用idfa功能所需要引入的頭文件(可選)
#import <AdSupport/AdSupport.h>
為AppDelegate添加Delegate。
參考代碼:
class AppDelegate: UIResponder, UIApplicationDelegate,JPUSHRegisterDelegate
主意:我們添加代理頭文件的話會報錯,因為我們需要設置代理以及實現倆個代理方法,說到這會有一個梗,但我們暫時先不談我們繼續先把流程跑通
參考代碼:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// 通知注冊實體類
if #available(iOS 10.0, *){
let entiity = JPUSHRegisterEntity()
entiity.types = Int(UNAuthorizationOptions.alert.rawValue |
UNAuthorizationOptions.badge.rawValue |
UNAuthorizationOptions.sound.rawValue)
JPUSHService.register(forRemoteNotificationConfig: entiity, delegate: self)
} else if #available(iOS 8.0, *) {
let types = UIUserNotificationType.badge.rawValue |
UIUserNotificationType.sound.rawValue |
UIUserNotificationType.alert.rawValue
JPUSHService.register(forRemoteNotificationTypes: types, categories: nil)
}else {
let type = UIRemoteNotificationType.badge.rawValue |
UIRemoteNotificationType.sound.rawValue |
UIRemoteNotificationType.alert.rawValue
JPUSHService.register(forRemoteNotificationTypes: type, categories: nil)//兼容舊版本
}
// 注冊極光推送
JPUSHService.setup(withOption: launchOptions, appKey: "xxxxxxxxxxxxxxxxxxxxxxxx", channel:"Publish channel" , apsForProduction: false)
}
部分參數說明:
appKey填寫管理Portal上創建應用后自動生成的AppKey值。請確保應用內配置的 AppKey 與 Portal 上創建應用后生成的 AppKey 一致。
channel指明應用程序包的下載渠道,為方便分渠道統計,具體值由你自行定義,如:App Store。
apsForProduction1.3.1版本新增,用于標識當前應用所使用的APNs證書環境。
0 (默認值)表示采用的是開發證書,1 表示采用生產證書發布應用。
注:此字段的值要與Build Settings的Code Signing配置的證書環境一致。
這里我們沒有用到IDFA如果有需要你們自行添加參數
注冊APNs成功并上報DeviceToken
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
JPUSHService.registerDeviceToken(deviceToken)
}
實現注冊APNs失敗接口(可選)
didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("APNs 注冊失敗")
}
添加處理APNs通知回調方法
//前臺進來走這個方法
@available(iOS 10.0, *)
func jpushNotificationCenter(_ center: UNUserNotificationCenter!, willPresent notification: UNNotification!, withCompletionHandler completionHandler: ((Int) -> Void)!) {
let userInfo = notification.request.content.userInfo as NSDictionary
if (notification.request.trigger?.isKind(of: UNPushNotificationTrigger.classForCoder()))! {
JPUSHService.handleRemoteNotification(userInfo as! [AnyHashable : Any])
}
completionHandler(Int(UNNotificationPresentationOptions.alert.rawValue))// 需要執行這個方法,選擇是否提醒用戶,有Badge、Sound、Alert三種類型可以選擇設置
print(userInfo)
}
//MARK: 后臺進來走這個方法
@available(iOS 10.0, *)
func jpushNotificationCenter(_ center: UNUserNotificationCenter!, didReceive response: UNNotificationResponse!, withCompletionHandler completionHandler: (() -> Void)!) {
let userInfo = response.notification.request.content.userInfo as NSDictionary
if (response.notification.request.trigger?.isKind(of: UNPushNotificationTrigger.classForCoder()))! {
JPUSHService.handleRemoteNotification(userInfo as! [AnyHashable : Any])
}
print(userInfo)
//這里我們可以自定義方法,用于指定界面的跳轉
completionHandler()
}
真機調試該項目,如果控制臺輸出以下日志則代表您已經集成成功。
2016-08-19 17:12:12.745823 219b28[1443:286814] | JPUSH | I - [JPUSHLogin]
----- login result -----
uid:5460310207
registrationID:171976fa8a8620a14a4
ok寫到這我們這就可以實現不報錯了但是這API竟然支持iOS9以上,歡迎大神給與我指點,但是不支持iOS8啊!那么我們繼續
添加以下代理方法
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
// print(userInfo)
if #available(iOS 9.0, *){
return
}else{
UIApplication.shared.applicationIconBadgeNumber = 0
/**
* iOS的應用程序分為3種狀態
* 1、前臺運行的狀態UIApplicationStateActive;
* 2、后臺運行的狀態UIApplicationStateInactive;
* 3、app關閉狀態UIApplicationStateBackground。
*/
// 應用在前臺 或者后臺開啟狀態下,不跳轉頁面,讓用戶選擇。|| (application.applicationState == UIApplicationState.background)
if (application.applicationState == UIApplicationState.active){
let alert = UIAlertController(title: "有推送發來的消息", message: "是否查看", preferredStyle: .alert)
let alertAction1 = UIAlertAction(title: "確定", style: .cancel) { (action) in
//相應代碼........
}
let alertAction2 = UIAlertAction(title: "取消", style: .destructive, handler: nil)
alert.addAction(alertAction1)
alert.addAction(alertAction2)
let resultVc = ZyzAuxiliary.getPresentedViewController()
resultVc?.present(alert, animated: true, completion: nil)
}else{
//殺死狀態下,直接跳轉到跳轉頁面
}
}
}
寫到這里估計讀者和我一樣的疑惑那我們什么不直接用著一個代理方法把所有的iOS版本都支持?然而我把上兩個代理方法去除以后JPUSHRegisterDelegate會報錯啊!我想極光這塊耦合性是不是高了點,這么來是不是讓那個我們的代碼工作量加大了?所以么有辦法,我才再次做了一個判斷iOS9作為分割點,這里我們需要注意的是當用戶在前臺的時候根據不同的版本合理調整跳轉機制以免造成無法跳轉或者重復跳轉的bug
講到這我大概的說一下后臺的知識,我們后臺一般需要registrationID,tags(標簽), alias(別名)等等. tags這個標簽,目前我們參數沒有要,因為這是需要比較大的用戶基數分析出來的,在推廣之前我們考慮還是不要浪費我們大數據團隊了,只加了alias,標簽的話, tags就是為了區分群體的,比如女性,男性,游戲愛好者,這離不開出色的數據分析團隊
和服務器交互的代理方法如下:
JPUSHService.registrationIDCompletionHandler { (resCode, registrationID) in
print("ID為\(String(describing: registrationID))" )
//我們的接口回調,不刪除了,參考一下吧
let Jsonsecret = ZyzGetMD5.getMD5(apiStr: kAPI_jpush)
let dic = ["secret":Jsonsecret,
"alias":NetworkRequestParameters.getIDFA(),
"registration_id":registrationID ?? ""
........
]
ZyzAFNworkManger.sharedManager().post(kAPI_jpush, parameters: dic, progress: nil, success: { (Task, responseObject) in
// print(" 服務器返回\(responseObject) ")
}, failure: { (Task, error) in
print(error)
})
}
分享一個個推不錯的文章截的圖
先寫到這吧,大家有什么疑問的歡迎私信,喜歡此文章的話歡迎大家點贊,分享,收藏或關注,有時間我會再給大家寫一篇關于iOS,APNs的原生推送