iOS - APNS流程

371 阅读7分钟

前言:这段时间,一直在进行着聊天模块的开发,介于之前,大家讨论的手机退到后台,由远程推送接力websocket的消息发送。正好借此机会,拓展一下,apple的推送服务。

推送种类

1.在线push

**在线push:**当用户在线(APP在前台)时,收到的状态栏的消息提醒,称为在线push。这个功能与苹果系统无关,是我们自己的APP开发的一种功能,该push与设置中是否打开“通知”无关,比如我们项目中的顶部横幅通知。

2.离线(远程)push

**离线push:**当APP在离线(kill掉进程、切到后台、锁屏)时,收到的消息提醒,称为离线push。离线push是需要经过苹果的APNs服务器才可以推送到某台设备的某个APP上的,这是和本地push的本质区别。push与设置中是否打开“通知”有关。

这里最简单的以大家常用的手机微信为例,当APP在后台、锁屏或者被kiil了进程时,收到的顶部消息通知。 首先我们看看离线(远程)push与静默push的区别: 普通离线(远程)push:收到推送后(有文字有声音),点开通知,进入APP后,才执行- (void)application:(UIApplication didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void result))handler *)application *)userInfo (^)(UIBackgroundFetchResult

静默push:收到推送(没有文字没有声音),不用点开通知,不用打开APP,就能执行- (void)application:(UIApplication )application)userInfo didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void (^)(UIBackgroundFetchResultresult))handler,用户完全感觉不到。

所以静默push又被我们称做 Background Remote Notification(后台远程推送)。静默推送是在iOS7之后推出的一种推送方式。它与其他推送的区别在于允许应用收到通知后在后台(background)状态下运行一段代码,可用于从服务器获取内容更新。

3.本地push

**本地push:**本地推送和远程推送的功能是一样的,都是要提醒用户去做某些事情。但是和远程推送不同的就是本地推送是不需要设备联网的,而远程推送是必需要设备联网的,因为只有联网状态下,才能和苹果的APNs服务器建立长连接,从而推送消息。本地推送是由app自己设定的,并且发送给安装此app的这台设备,属于一对一的对应关系。比较典型的应用是闹钟类似的场景。该push与设置中是否打开“通知”有关。

最容易看到本地push的场景,可以直接在手机设置一个计时器,计时器时间到了就会弹出本地push。

启动离线(远程)push流程

启用推送通知功能

要将所需的推送服务功能添加到app配置中,需要在 Xcode 项目中启用推送通知功能。

启用推送通知功能通过在 Capabilities 选项卡中启用推送通知功能,为您的 Xcode 项目添加权利。

开启后,会在开发者帐户中,为分配的项目启用推送通知服务。

在app中注册并检索app的device token

在应用程序注册使用 APNs,并接收唯一的device token,这实际上是app在当前设备上的地址。服务器必须拥有device token,才能将通知发送到设备。

每次启动应用程序时,需要使用 Apple 提供的 API 注册应用程序,并接收device token。不同平台的注册过程类似:

除了使用 APNs 处理成功注册之外,通过实现application(_:didFailToRegisterForRemoteNotificationsWithError:)方法,处理注册失败。如果用户的设备未连接到网络,如果 APNs 服务器因任何原因无法访问,则注册可能会失败。发生这些注册失败的情况时,设置一个标志并在合适的时机重新注册。

下面是注册远程通知和接收相应device token所需的委托方法。

在启动时与 APNs 通信

func application(_ application: UIApplication,  didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {  
  // Override point for customization after application launch.you’re            
  UIApplication.shared.registerForRemoteNotifications()   
  return true
}

func application(_ application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken   deviceToken: Data) {   
  self.sendDeviceTokenToServer(data: deviceToken)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError    error: Error) {   
  // Try again later.
}

永远不要在本地存储中缓存设备令牌。当用户从备份恢复设备、用户在新设备上安装应用程序以及用户重新安装操作系统时,APNs 会生成一个新的device token。

将device token 分发到 推送服务器

收到device token后,打开从app到服务器的网络连接。将device token和用户所需的其他信息,安全地发送到服务器。

将device token存储在服务器上,可以访问它们来发送通知。生成通知时,服务器必须能够向特定设备发送通知。因此,如果通知与用户帐户相关联,需要将device token与用户帐户信息一起存储。

设置远程通知服务器

使用远程通知(也称为推送通知)将少量数据推送到使用app的设备,即使app没有运行。app也可以使用通知向用户展示重要信息。

远程通知的传递涉及几个关键部分:

  • 公司的服务器,称为提供商服务器
  • Apple 推送通知服务 (APNs)
  • 用户的设备
  • 应用在用户设备上运行

远程通知从公司的服务器开始。可以决定要向用户发送哪些通知,以及何时发送。当需要发送通知时,会生成一个请求,其中包含通知数据和用户设备的唯一标识符。然后,将请求转发给 APNs,后者负责将通知传送到用户的设备。收到通知后,用户设备上的操作系统会处理用户交互并将通知传递给应用程序。

您公司的提供商服务器与 Apple Push Notification 服务通信,后者又与用户的设备通信。

在App中注册APNs服务

与 Apple 推送通知服务 (APNs) 通信并接收用于识别app的唯一设备令牌(device token)。

Apple 推送通知服务 (APNs) 必须知道用户设备的地址,然后才能向该设备发送通知。此地址采用设备和app唯一的device token的形式。在启动时,app与 APNs 通信并接收其device token,然后将其转发到后台服务器。

一个app的device token不能用于另一个应用程序,即使两个app都安装在同一设备上。两个app都必须请求自己的唯一device token并将其转发到后台服务器。

离线(远程)push流程总结

sequenceDiagram
    participant APNs
    participant Hiintern iOS App
    Hiintern iOS App->>APNs:1.调用官方Api,申请deviceToken
    APNs->>Hiintern iOS App:2.下发deviceToken!
    Hiintern iOS App->>服务器:3.将deviceToken存储在服务器
    服务器->>APNs:4.当满足某些条件时,给设备推送远程通知
    APNs->>Hiintern iOS App:5.发送推送通知!

为什么要用第三方推送服务

接触过推送服务的同学们,应该都有听说过极光推送、友盟推送、腾讯信鸽、小米等等第三方推送服务商。那么苹果的APNs这么好用,为何还要使用第三方推送服务商呢?

  • 在 iOS 平台上,苹果有其官方推送平台 APNS(Apple Push Notification service),开发者可以直接使用该推送服务,但是提供的功能非常有限。(提供一些基础的服务,扩展需要开发者自行定制)
  • 安卓平台在一开始推出的时候并没有考虑到统一推送平台的问题,所以在安卓平台上是没有一个统一的推送解决方案的。虽然后面安卓平台也推出了自己的 GCM (Google Cloud Messaging)推送平台,但开发者都习惯使用了自己的第三方推送服务,想改也很难了。
  • 因为 Android 使用了第三方推送,一般情况下都会要求 iOS 端也使用第三方推送,这是为了保持移动端实现的统一。