前文介绍了通知的本地推送,本文接着再介绍下远程推送。

六、远程推送基本介绍

1,什么是远程推送

  • 远程通知是指在联网的情况下,由远程服务器推送给客户端的通知,又称 APNs(Apple Push Notification Services)。
  • 由于在联网状态下,所有苹果设备都会与苹果服务器建立长连接。所以不管应用是打开还是关闭的情况,都能接收到服务器推送的远程通知。

2,实现原理

(1)App 打开后首先自动发送 UDID 和 BundleID 给 APNs 注册,并返回 deviceToken。

(2)App 获取 deviceToken 后,调用接口将用户身份信息和 deviceToken 发送给我们的服务器,服务器将其记录下来。

(3)当要推送消息时,服务器按照用户身份信息找到存储的 deviceToken,将消息和 deviToken 发送给 APNs。

(4)苹果的 APNs 通过 deviceToken,找到指定设备的指定程序, 并将消息推送给用户。

3,准备工作

要开发测试远程推送功能,我们需要准备如下两个东西:

  • 真机:使用模拟器是没法注册 APNS,自然也就无法实现远程通知。
  • 推送证书:这就要求我们必须要有个苹果开发者帐号

4,证书申请

(1)首先我们需要创建应用的 APNs 证书。如果对 APNs 证书不太了解,可以请参考: iOS 证书设置指南

(2)根据指南中的“方式一”,我们创建一个推送证书(aps.cer)。将其下载到本地,并双击安装即可。

七、远程推送样例

1,客户端准备工作

项目配置好证书后,还要打开下图的开关。

2,客户端代码

下面是 AppDelegate.swift 的代码。我们同样是先去获得通知权限后。不过对于 APNs 而言,还需要多一个获取用户 DeviceToken 的操作(高亮部分)。

  • 实际应用中我们会把这个 DeviceToken 传递给我的的服务器,服务器后面就可以使用这个 DeviceToken 向 Apple Push Notification 的服务器提交请求,然后 APNs 通过 DeviceToken 识别设备和应用,将通知推给用户。
  • 由于获取得到的 DeviceToken 是一个 Data 类型,为了方便使用和传递,通常会将它转换为一个适合传递给 Apple 的字符串(通过 Data 扩展实现)。这里我们直接将转换后的 DeviceToken 字符串打印出来。
    import UIKit
    import UserNotifications

    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    let notificationHandler = NotificationHandler()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions
    launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    //请求通知权限
    UNUserNotificationCenter.current()
    .requestAuthorization(options: [.alert, .sound, .badge]) {
    (accepted, error) in
    if !accepted {
    print("用户不允许消息通知。")
    }
    }

    //向APNs请求token
    UIApplication.shared.registerForRemoteNotifications()

    return true
    }

    //token请求回调
    func application(_ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    //打印出获取到的token字符串
    print("Get Push token: \(deviceToken.hexString)")
    }

    func applicationWillResignActive(_ application: UIApplication) {
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
    }

    func applicationWillTerminate(_ application: UIApplication) {
    }
    }

    //对Data类型进行扩展
    extension Data {
    //将Data转换为String
    var hexString: String {
    return withUnsafeBytes {(bytes: UnsafePointer<UInt8>) -> String in
    let buffer = UnsafeBufferPointer(start: bytes, count: count)
    return buffer.map {String(format: "%02hhx", $0)}.reduce("", { $0 + $1 })
    }
    }
    }

3,测试运行

(1)接上手机,编译运行程序。可以看到我们已经成功获取到了推送 token。特别要注意的是:

  • app 重新启动后,token 是不会变化的。
  • app 卸载重新安装的话,token 就会发生变化。

(2)通常来说我们会有个服务端,然后通过这个 token 给对应的设备推送通知。这里为了方便测试,我们使用 APNs 调试工具 Knuff。下载地址:https://github.com/KnuffApp/Knuff/releases

(3)Knuff 使用方法如下:

  • Custom:自定义模式。我们测试自己的应用,就用这个模式,可以自行选择证书。
  • Choose:选择推送证书。也就是我们文章最开头申请的证书。
  • Sandbox:表示推送给开发版本的 App(非 AppStore 版本)。
  • Token:即我们上面注册苹果 APNs 服务时获取到的 device token。
  • Payload:表示要推送的报文。

(4)上面这些设置好以后,点击“Push”按钮即可发送远程通知。这时手机这边就可以收到这条推送消息。

(5)上面的推送报文比较简单,通知只有一个标题(title)和应用图标标记(badge)。这次我们再增加内容(body)、子标题(subtitle)。

{
"aps":{
"alert":{
"title":"hangge.com",
"subtitle":"航歌",
"body":"做最好的开发者知识平台"
},
"sound":"default",
"badge":1
}
}

手机收到通知效果如下: