iOS Push Notification 之 Background RemoteNotification

Background RemoteNotification

最近在调查iOS Push Notification, 发现Background RemoteNotification这个功能还挺有意思的,做一下记录:

  • 版本需求: iOS 7以上
  • 使用方法:指定 aps 字段 "content-available" : 1
  • 功能:在收到通知时,唤醒后台应用并执行自定义处理逻辑,可以用于从网络获取数据

准备条件

  • APNs 证书
  • 在Xcode target中打开Push Notification和Background Modes中的Remote notifications
  • 任意能发送Push Notification的服务(Firebase,OneSignal之类)

处理逻辑

AppDelegate中添加:

func application(_ application: UIApplication, 
    didReceiveRemoteNotification userInfo: [AnyHashable : Any], 
    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    // Network etc...       
        Alamofire.request("https://httpbin.org/get").responseJSON { response in
            print("DidReceiveRemoteNotification finished!")
            completionHandler(.newData)
        }
    }

测试

对于不同状态下的应用,进行了如下实际测试:

  • 前台:didReceiveRemoteNotification会被调用
  • 后台:didReceiveRemoteNotification会被调用
  • 网络无法连接/飞行模式
    :开启飞行模式后发送通知,3分钟后开启应用,didReceiveRemoteNotification会被调用
    (长时间飞行模式后能否收到未测试)
  • 系统关闭通知:didReceiveRemoteNotification会被调用
  • 强行退出:"priority"默认为中的情况下,通知无法收到
    (手动设置"priority":"high"
    通知可以收到)
    didReceiveRemoteNotification不会被调用

测试环境:

  • iOS10
  • iPhone 7 Plus

其他

根据官方文档, DidReceiveRemoteNotification 不保证被调用, 应用强行退出后不会被调用
DidReceiveRemoteNotification 调用时机不确定:background-fetch-triggers-too-late

另外,aps中如果不指定"alert"等Notification字段,可以实现不通知用户的情况下更新应用内内容
(SilentNotification)

用于数据统计的应用场景

通过这个功能,可以实现以下数据的统计:

  1. 收到消息的用户数量 MsgRcvd(开启通知并收到通知用户数 MsgRcvd_on + 禁用通知但收到通知用户数 MsgRcvd_off”)
  2. 打开消息的用户数量 MsgOpen
  3. 忽略了消息的用户数量 MsgRcvd_on - MsgOpen
  4. 禁用通知用户数 MsgRcvd_off
  5. 注册的APNs数量 MsgTarget
  6. 不明 MsgTarget - MsgRcvd (飞行模式中,关机,应用未打开,系统暂缓后台操作,应用删除,应用强制退出)

通知条件

带有 "notification":{body}"content_available"
(例中使用FCM的通知服务,对应"content_available": 1

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: key=AI" \
-d '{
    "to": "/topics/movies",
    "content_available": true
    "notification" : {
        "body" : "API Send to movies"
    },
    "data": {
        "dataA" : "t00003x1bg"
    }
}' "https://fcm.googleapis.com/fcm/send"

处理逻辑

  • application didReceiveRemoteNotification:fetchCompletionHandler:中检测用户通知状态

  • 根据用户通知状态发送 “已经收到通知 MsgRcvd_on"或“已经收到通知 MsgRcvd_off”事件

  • 系统通知开启状态时, 在用户打开通知处理逻辑userNotificationCenter didReceive response中发送“打开通知 MsgOpen”事件

数据的收集和统计可以利用Firebase Analytics之类的服务。

Ref:

  1. Local and Remote Notification Programming Guide
  2. Firebase Cloud Messaging HTTP Protocol
comments powered by Disqus