iOS - 推送技术调研

一、简介

消息通知可以在程序处于后台或者关闭状态,向使用者推送信息,例如接收到消息,或者有新的推送等。
当接收到消息通知时,一般会有以下几种表现:

  • 在屏幕顶部显示横幅
  • 在屏幕显示UIAlertView提示信息
  • 在锁屏界面显示横幅
  • APP的角标显示数字
  • 提示音

iOS中提供了2中推送通知:

  • 本地消息通知
  • 远程推送通知

二、本地通知

本地通知的特点就是不需要联网。

实现场景打开软件后,软件在后台时,闹钟功能,简单的提醒功能等。

1、本地推送例子:

首先需要在使用本地通知之前,需要先获得用户的授权。

Swift
1
2
3
4
5
6
7
8
9
10
override func viewDidLoad() {
super.viewDidLoad()
UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) { (success, error) in
if success {
print("success")
} else {
print("error")
}
}
}

实现通知方法:

Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func registerLocalNotification(alertTime: NSInteger, alertBody:String,userDict: NSDictionary){
let localNoti = UILocalNotification()
// 设置触发通知的时间
let fireDate = NSDate().addingTimeInterval(TimeInterval(alertTime))
localNoti.fireDate = fireDate as Date
// 设置时区
localNoti.timeZone = NSTimeZone.default
//通知上显示的主题内容
localNoti.alertBody = alertBody
//收到通知时播放的声音,默认消息声音
localNoti.soundName = UILocalNotificationDefaultSoundName
//待机界面的滑动动作提示
localNoti.alertAction = "打开应用"
//应用程序图标右上角显示的消息书
localNoti.applicationIconBadgeNumber = 0
//通知上绑定的其他信息
localNoti.userInfo = (userDict as! [AnyHashable : Any])

//添加通知到系统队列,系统会在指定的时间触发
UIApplication.shared.scheduleLocalNotification(localNoti)
}

以上方法已经初步实现触发本地通知的功能了。但需要完整实现,还需要在 Appdelegate.swift(OC 中为 AppDelegate.m)实现当应用程序进入前台或处于前台时对本地推送的处理。后问的远程推送也有类似操作。

Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//应用程序在进入前台,或者在前台的时候都会执行该方法
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
//必须要监听 -- 应用程序在后台的时候进行的跳转
if application.applicationState == .inactive {
// 获取通知上绑定的信息
guard let dict = notification.userInfo else {
return
}

// 后面作相应处理...
}else if application.applicationState == .active{

}else{

}
}

二、远程推送

远程推送的服务的实现依据的是服务器和客户端的长连接,信息通过服务器主动推送(push)给客户端(我们的手机)。

但 Apple 对设备的控制非常严格,消息推送的流程必须要经过 APNs(Apple Push Notification service),所以具体推送流程概括如下:

1、远程推送例子:

(1)首先需要在开发者账号里配置应用推送证书。过程略。
(2)打开应用工程,勾选Backgroud Modes -> Remote notifications,主要是iOS7之后,苹果支持后台运行,如果这里打开后,当接收到远程推送后,程序在后台也可以做一些处理,如下图所示:
-w1001

(3)远程推送的注册

Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import UserNotifications

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

UNUserNotificationCenter.current().getNotificationSettings { (settings) in
switch settings.authorizationStatus {
case .authorized:
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
case .notDetermined:
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound]) { (granted, error) in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
default:
break
}
}

return true
}
// 这个函数存在的意义在于:当用户在设置中关闭了通知时,程序启动时会调用此函数,我们可以获取用户的设置
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[application registerForRemoteNotifications];
}

如果注册失败,比如没有证书等等,会调用:

Swift
1
2
3
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("远程通知注册失败:\(error)")
}

(4)获取 deviceToken
如果用户同意,苹果会根据应用的 bundleID 和 手机UDID 生成 deviceToken,然后调用 application 的 didregister 方法返回 devicetoken,程序应该把 devicetoken 发给应用的服务器,服务器有义务将其存储(如果允许多点登录,可能存多个 devicetoken)。deviceToken也是会变的: ”If the user restores backup data to a new device or computer, or reinstalls the operating system, the device token changes“,因此应每次都发给服务器(provider)

Swift
1
2
3
4
/// 用户同意后,会调用此程序,获取系统的deviceToken,应把deviceToken传给服务器保存,此函数会在程序每次启动时调用(前提是用户允许通知)
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("deviceToken = \(deviceToken)")
}

(5)用户点击了通知
当应用是被通知打开的时候,你可以通过 application:didFinishLaunchingWithOptions:方法的 launchOptions 参数所使用的 dictionary 访问到数据:

Swift
1
2
3
4
5
6
7
8
unc application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

if let notification = launchOptions?[.remoteNotification] as? [AnyHashable: Any] {
print(notification)
}

return true
}

如果当通知到达的时候,你的应用已经在运行,对于 iOS10 以下,你可以通过 application:didReceiveRemoteNotification:fetchCompletionHandler: 方法的 userInfo 参数所使用 dictionary 访问到数据:

Swift
1
2
3
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// handle notification
}

iOS10 以上需要使用下面代理方法来获得 userInfo :

Swift
1
2
3
4
5
6
7
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// handle notification
}

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// handle notification
}

2、远程推送平台比较

(1)个推

国内目前关注量最多的一个推送平台,客户端SDK支持Android和iOS两大平台,云端支持丰富的网页端推送管理功能和多种语言版本的API开放接口,个推提供针对单个用户推送、针对一组用户批量推送、以及根据特定省市、特定用户标签进行精准推送等多种推送方式。
集成方式:支持手动集成和 cocoapod 集成。两种方式都很方便。支持 OC 和 swift 集成。SDK 包有 demo。但同一时间支持一种证书测试。用最新版本的 SDK 上架时需要勾选广告标识符(IDFA),如果不想勾选,只能使用旧版本 SDK。对开发者不太友好。而且两种方式导入都需要导入一个 GTExtensionSDK 的依赖包,但这个依赖包只支持 10.0 以上的版本。

  • 开发文档:比较规范。比较详细,针对各个 iOS 版本(最低有 10.0)的推送方法都有注明。比较精确,头文件的引用和注释,方法的使用和可拓展的方法预留及注释。但和 极光 对比缺少一些失败回调方法的说明。
  • 实际集成:按照文档尝试使用 无 IDFA 的 SDK,用 cocoapod 集成。pod install 后工程报错。后续没再尝试。
  • 功能:支持通知推送,静默推送,消息透传。支持按标签、国家地区推送。
  • 收费情况:免费,但有 免费 和 vip 的区别。推送数免费的没有次数限制,但有用户数限制。和极光推送一样,推送速度,20万条每秒(共享),vip 为独享。

(二)、百度云推送

百度云推送(Push)是百度云平台向开发者提供的消息推送服务;通过云端与客户端之间建立稳定、可靠的长连接来为开发者提供向用户端实时推送消息的服务。支持Android/iOS平台、支持更多自定义功能(如自定义内容、后续行为、样式模板等)、支持地理位置的推送(或”LBS推送”)。

  • 无法直接创建应用,需要向百度工作人员发送申请邮件。尝试发送邮件,没得到回应,就放弃体验了。

(3)极光推送

极光推送,英文简称JPush,是一个面向普通开发者开放的,免费的第三方消息推送服务。 轻量级的客户端SDK:开发者只需在客户端集成极光推送SDK,即可轻松地添加Push功能到他的App中。极光推送支持Android、iOS、windows phone。 云推送服务:开发者可以在管理Portal上快捷地向用户推送消息,也可以定制推送的时间、用户群、位置等,还提供远程推送API。 推送效果分析图表:开发者可以在管理Portal上查看推送统计信息,直观地评估推送效果。
集成方式:支持手动集成和 cocoapod 集成。手动集成相对繁琐,需要导入很多依赖库。支持双证书。SDK 包有 demo。

  • 开发文档:比较规范。详细,针对各个 iOS 版本(最低有 6.0)的推送方法都有注明。精确,包括极光平台获取 devicetoken 需要开始开始 http 支持,有写如何根据域名配置只支持 极光 http。头文件的引用和注释,方法的使用和可拓展的方法预留及注释。
  • 实际集成:按照文档集成进 SDK,实现方法,运行未报错。但后台有新的设备上线,测试推送消息可以接收到。
  • 功能:支持通知推送,和自定义消息(只有在前端运行的时候才能收到自定义消息的推送。从 JPush 服务器获取用户推送的自定义消息内容和标题以及附加字段等。可实现静默推送的需求)。支持标签、国家地区,系统版本,活跃用户,
  • 收费情况:免费,但有 免费 和 VIP 的区别。但区别影响不是很大,推送次数没有限制,推送速度可能比 VIP 慢。

(4)友盟
-w1292

  • 集成方式:支持手动集成和 cocoapod 集成。两种方式都很方便。支持双证书。SDK 包无 demo。
  • 开发文档:比较杂乱。不是很详细,针对各个 iOS 版本的推送方法没有都注明。不是很精确,对于某些方法提供了调用例子,但是没有说明具体在哪里调用。
  • 实际集成:按照文档集成进 SDK,实现方法,运行未报错。但后台也没有新的设备上线,测试推送消息也无法接收到。
  • 功能:支持通知推送,静默推送,应用内消息(开屏消息(开屏消息就是当app启动,或者从其他页面跳转到app时,调用的一个启动页面),插屏消息),富文本推送。支持按应用版本,系统语言,国家地区,机型,用户活跃度推送。
  • 收费情况:免费,但有 免费 和 Pro 的区别。推送速度、推送次数有不同。

总结:通过以上老牌和新出的推送服务对比,结合实际集成体验,推荐使用 极光推送。如果需要更深度的定制需求,推荐使用 友盟。

------本文结束 感谢阅读------

本文地址:http://kaaaaai.cn/articles/iOS-push-technology-research.html
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
转载请注明出处,谢谢!

众筹项目:拯救世界!
0%