iOS推送通知后台模式
refer to: How to handle remote notification with background mode enabled
这些年iOS推送功能已进化非常强大,从只能简单提示一串文字,到如今包括自定义事件、本地化文字、后台模式,已是一套成熟的系统。 这篇文章描述了一条通知到达设备,发生的一切。
调用了哪一个代理方法
那是推送到达设备时应回答的问题。
四个的回调:
application(_:didReceiveRemoteNotification:)
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
userNotificationCenter(_:willPresent:withCompletionHandler:) (iOS 10.0, *)
NO callback
UIApplicationDelegate中还有其它回调方法,但除非有必要,不然这个讨论中忽略掉。详细的如下:
当打开通知的时候调用:
application:didReceiveRemoteNotification: (iOS 3.0)- 这是原始API。现在已被application(:didReceiveRemoteNotification:fetchCompletionHandler:)_(iOS 7.0)取代。 application(:handleActionWithIdentifier:forRemoteNotification:completionHandler:)_(iOS 8-10)支持自定义通知事件 userNotificationCenter(:didReceive:withCompletionHandler:)_ (iOS >= 10) 支持自定义通知事件
An advanced topic we shelf off for now.
配置payload 和 静默推送
推送通知 payload 组成如下:
- alert - the alert string and actions
- badge
- sound
- content-available
content-available键是一个新特性,而且就是这个键式静默推送成为可能。如果要静默推送,你太同时需要在“Capabilities”的UIBackgroundModes中添加remote-notifcation。
当ontent-available存在payload中时:
- 如果应用Suspended,系统会使它进入Background运行模式
- 如果应用被用户杀死,什么事都不会发生,并且应用无法运行读取应用状态
A potential is pitfall:
注意事项:
content-available=1开启静默推送,但是关闭静默推送并不是content-available=0。而是删掉payload中的键。
不同场景
content-available启用时
应用处于Foreground
没有弹出框
application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10)被调用 userNotificationCenter(:didReceive:withCompletionHandler:)_ (iOS >= 10) 被调用
应用处于 Background
系统会弹出提示框
application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS >= 7)被调用
应用处于 Suspended
应用状态会变为Background
系统会弹出提示框
application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10)被调用 userNotificationCenter(:didReceive:withCompletionHandler:)_ (iOS >= 10) 被调用
应用被用户杀死
系统会弹出提示框
不会有回掉
content-available未启用时 (键被移除)
- 应用处于Foreground 没有提示框 application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10)被调用 userNotificationCenter(:willPresent:withCompletionHandler:)_ (iOS >= 10)被调用
- 应用处于 Background 或者 Suspended 系统会弹出提示框 不会有回调,但是用户点击推送打开应用时 application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10)被调用 userNotificationCenter(:didReceive:withCompletionHandler:)_ (iOS >= 10) 被调用
- 应用没有runing时 系统会弹出提示框 不会有回调,但是用户点击推送打开应用时 先调用application(:didFinishLaunchingWithOptions:)_ 然后application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10)被调用 userNotificationCenter(:didReceive:withCompletionHandler:)_ (iOS >= 10) 被调用
总结
如果应用处于Foreground,系统不会弹出提示框。当调用application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10) userNotificationCenter(:willPresent:withCompletionHandler:)_ (iOS >= 10)后才呈现某些UI元素。
启用content-available会使应用处于Background模式 (除非应用是被用户杀死) 然后调用 application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10) userNotificationCenter(:didReceive:withCompletionHandler:)_ (iOS >= 10)
若未启用 content-available, 应用会一直处于Suspended, 并且 application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10) userNotificationCenter(:didReceive:withCompletionHandler:)_ (iOS >= 10) 不会被调用,除非用户点击推送。
最后, application(:didFinishLaunchingWithOptions:)_ 只会在应用Not Runing时调用。用户点击推送,会调用 application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10) userNotificationCenter(:didReceive:withCompletionHandler:)_ (iOS >= 10)。所以: 推送后台处理都在:application(:didReceiveRemoteNotification:fetchCompletionHandler:)_。 推送前台处理:application(:didReceiveRemoteNotification:fetchCompletionHandler:)_ (iOS < 10)需要判断应用状态
//所有后台处理
if application.applicationState == .background {
//对应的UIBackgroundFetchResult
completionHandler(UIBackgroundFetchResult.newData)
}
//iOS < 10 用户点击通知消息处理
if application.applicationState != .background && ProcessInfo.processInfo.operatingSystemVersion.majorVersion <= 9{
}
userNotificationCenter(:willPresent:withCompletionHandler:)_ (iOS >= 10)