iOS - APNS 远程推送

参考文档

  • Mobile push notifications
  • Setting Up a Remote Notification Server

开始集成 iOS 的远程推送,先在苹果开发者账号配置好推送证书后,开始进行代码开发

第一步,获取通知权限,系统通知框只会出现一次,如果用户拒绝授权。根据需要通过获取当前通知权限,去弹一个提示用户前往 System Setting 打开授权的自定义弹窗

前往 System Setting 页面的示例代码如下

UIApplication.shared.open(URL.init(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)

iOS 10.0 开始支持 UNUserNotificationCenter,直接通过 UNUserNotificationCenter 请求通知权限

// 该方法会触发 
UIApplication.shared.registerForRemoteNotifications() 

let center = UNUserNotificationCenter.current()
//        center.delegate = self
center .requestAuthorization(options: [.sound, .alert]) { (grand, error) in
   if (error != nil) {

    }else {

    }
}

获取到推送权限之后,我们需要在移动端获取注册后的 device-token,然后将 device-token 传到我们的后台

// 获取用于注册的 DEVICE_TOKEN
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

  var deviceTokenString = ""
  let bytes = [UInt8](deviceToken)
  for item in bytes {
      deviceTokenString += String(format:"%02x", item&0x000000FF)
  }

  // 获取到 DEVICE_TOKEN 后和用户账号进行绑定

}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {

}

提交完成后,当我们接收到推送消息时在 didReceiveRemoteNotification 代理方法中进行消息处理

// 已经收到通知
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

  // UIApplication.State 有三种状态: inactive/active/background

  // inactive 是处理应用从后台跳转前台,还是从前台到后台的事件触发状态

  if application.applicationState == .inactive {
      guard let navi = window?.rootViewController as? UINavigationController else { return }
      navi.pushViewController(DeviceManagementViewController.init(), animated: true)
  }

}

推送消息分为两种格式:透传消息、通知栏消息

  • 通知栏消息,当设备在后台收到远程推送后,立刻弹出通知栏,开发者没办法控制通知栏的弹出
  • 通过透传消息可以自定义消息格式,然后在前台做 UI 的多样式展示

通知栏消息的格式参考 Generating a Remote Notification,其中 alert 字典中的 title、subtitle、body 中可以控制消息通知的标题、副标题、内容

{
   "aps" : {
      "alert" : {
        
         "title" : "Game Request",
         "subtitle" : "Five Card Draw",
         "body" : "Bob wants to play poker"
      },
      "category" : "GAME_INVITATION"
   },
   "gameID" : "12345678"
}

展示效果如下图所示

如何实现在前台,当收到消息的时候也弹出通知栏

/// 添加 UNUserNotificationCenter 的 代理
/// 实现 UNUserNotificationCenterDelegate 的 userNotificationCenter 方法
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            willPresent notification: UNNotification, withCompletionHandler
                                completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.badge, .sound, .alert])
}

App icon 角标处理,苹果的推送消息会根据 JSON 中 apns 的 badge 字段进行角标数量的设置,然后在 App 端进行启动后的 -1 或者清空

// 角标数量清空
UIApplication.shared.applicationIconBadgeNumber = 0

推送测试

在 iOS 中我们可以使用命令行进行推送测试,参考文档见 Sending Push Notifications Using Command-Line Tools

文档中有两种方式进行推送: 证书、device-token;这里只讲一下利用 device-token 发送推送的方式:

在终端新建 shell 文件,这里命名为 push-remote-notification

touch push-remote-notification.sh
vim push-remote-notification.sh

编辑 shell 脚本,这里需要 der 和 pem 证书,如果已经有了 p12 证书,可以通过 openssl 进行转换

# 下面的变量需要根据实际情况修改
CERTIFICATE_FILE_NAME={DER 证书路径}
CERTIFICATE_KEY_FILE_NAME={PEM 证书路径}
# bundle id
TOPIC={appid}
DEVICE_TOKEN={device-token}
# 生产环境
# APNS_HOST_NAME=api.push.apple.com
# 开发环境
APNS_HOST_NAME=api.sandbox.push.apple.com

curl -v --header "apns-topic: ${TOPIC}" --header "apns-push-type: alert" --cert "${CERTIFICATE_FILE_NAME}" --cert-type DER --key "${CERTIFICATE_KEY_FILE_NAME}" --key-type PEM --data '{"aps":{"alert":"test"}}' --http2  https://${APNS_HOST_NAME}/3/device/${DEVICE_TOKEN}

运行 shell 脚本

sh push-remote-notification.sh

你可能感兴趣的:(iOS - APNS 远程推送)