在设备上推送通知到达(未收到)时,代理被调用
我知道,当推送通知到达设备上(并且应用程序未打开它)时,没有办法检查(我可能会错误)。但是在我的应用程序中有一个这样的情况,那就是必须知道通知已到达设备。
我在应用程序中有多个选项卡,其中2个根据推送通知具有徽章实施。所以基本上有两种不同类型的推送通知。在设备上推送通知到达(未收到)时,代理被调用
假设如果一种类型的通知到达设备和用户选择不看通知。这样,一个特定标签的徽章计数被递增由1。但问题是,哪一个。因为当时我打开了应用程序,我没有那些通知类型已经到达的信息。或者更确切地说,哪个标签徽章计数将被递增。 所以简而言之,我怎么知道,通知已到达设备(未收到)?
无法使用公共API获取此信息。
从Local and Remote Notifications Programming Guide:
让我们回顾一下,当系统 提供了一个本地通知或应用程序的远程通知可能出现的可能的情况。
通知在应用程序没有在 前台运行时传递。在这种情况下,系统会显示通知, 显示警报,标记图标,可能播放声音,并且可能会显示一个或多个操作按钮供用户点按。
用户点击iOS 8通知中的自定义操作按钮。在这种情况下,iOS调用 application:handleActionWithIdentifier:forRemoteNotification:completionHandler: 或 application:handleActionWithIdentifier:forLocalNotification:completionHandler :. 在这两种方法中,您都可以获得操作的标识符,以便您可以确定用户点击哪个按钮。您还可以获得远程 或本地通知对象,以便您可以检索任何需要处理该操作的信息 。
用户点击提醒中的默认按钮或点击(或点击) 应用程序图标。如果轻击默认操作按钮(在运行iOS的设备上),系统启动应用程序,应用程序调用其应用程序:didFinishLaunchingWithOptions:方法,传入 通知负载(用于远程通知)或 local-通知对象(用于本地通知)。尽管 应用程序:didFinishLaunchingWithOptions:不是 处理通知的最佳位置,但在此时获取有效负载将使您 有机会在调用处理程序方法 之前启动更新过程。
对于远程通知,系统还会调用 应用程序:didReceiveRemoteNotification:fetchCompletionHandler: 应用程序委托的方法。
如果在运行OS X的计算机上单击应用程序图标,应用程序会调用 代理的applicationDidFinishLaunching:代理可以获取远程通知有效负载的方法。如果在运行iOS的设备上轻按应用图标 ,该应用将调用相同的方法,但 不会提供有关该通知的信息。
正如您所看到的,当应用程序从死亡状态或未锁定状态开始时,只能检查点击通知。
另外重要的一点是:
服务质量
苹果推送通知服务包括执行一个存储和转发功能服务 (QoS)的组件的默认质量。如果APN 尝试传递通知但设备处于脱机状态,则 通知将存储一段有限的时间,并在设备可用时传送至 。只有一个最近通知 的特定应用程序被存储。如果在 设备处于脱机状态时发送了多个通知,则新通知将导致先前的 通知被丢弃。只保留最新的 通知的行为称为合并通知。
如果设备长时间保持脱机状态,则会丢弃为其存储的任何通知 。
所以,长话短说,交货&存在推通知是高度可预期的,但不能保证。此外,设备上的推送通知路径不会以编程方式控制 - 作为应用程序,您在设备上订阅APNS守护程序,并且您依赖推送通知。
这就是为什么,如果你的应用程序有一些业务逻辑(在你的情况下,计数器更新),你不应该依赖推送通知。您应该使用更可靠/可控的机制来同步应用程序和后端之间的数据。我通过使用REST并在我的应用程序的问题域中专门使用Notification
实体几次实现了这一目标 - 用户可以获取通知,将它们标记为已读/未读,并通过REST API删除它们等。
感谢您的解释。说得通。似乎像Facebook这样的应用程序使用私有API来实现此目的。我喜欢你创建单独的实体来处理通知的方法。使功能更清晰。 – Nitish
我相信,facebook和linkedin没有使用私有API - AFAIK,它们为每个选项卡(Messenger,通知,朋友请求,当它关于Facebook和LinkedIn几乎相同)都有单独的计数器。我认为,他们使用REST或一些websocket机制来获取更新和某种缓存。如果你在Facebook应用程序的启动早期有徽章计数 - 它们从缓存中获得99.99%,然后通过网络连接从网络更新 –
你可以给出关于最后一句话的更多细节:“我已经实现了这个目标很少通过使用REST并在我的应用的问题域中专用通知实体 - 用户可以获取通知,将它们标记为已读/未读,通过REST API删除它们等“ – Honey
如果用户通过单击通知或者如果应用程序处于打开状态来打开应用程序,则只能获取通知有效负载信息。在这两种情况下,didReceiveRemoteNotification都会调用。除此之外,您可以在应用程序打开时调用服务器上包含通知计数信息的服务。
您可以将一些参数添加到json
接收到推送通知中的数据中,例如"type":1
以识别通知的类型。见Examples of JSON Payloads。但是来自API的通知的加载计数更好,然后将每种类型的通知计入应用程序。
您可能可以通过为推送通知使用后台提取模式来解决此问题。将您的特殊徽章号存储到某种持久性存储(可能是用户默认值)并在打开应用程序时使用该值。
有关背景提取,考虑这样一个问题: Will iOS launch my app into the background if it was force-quit by the user?
但是,要知道,用户可以选择从后台退出获取。
所以基本上,总结别人的话,你会有两个用户案例。但是在你需要在你的有效载荷中指定哪个徽章必须增量之前(如@Andrew建议)。 下面是用户案例:
- 应用程序可以调用
didReceiveRemoteNotification
。在这种情况下,这意味着该应用程序处于后台或前台,或者通过点击通知启动。你将不得不实施你的逻辑来处理这种情况。只是解析你的通知的有效载荷(在JSON中)并确定你应该增加哪个徽章。 - 该应用不能拨打
didReceiveRemoteNotification
。在这种情况下,用户已经杀死了您的应用,或者该设备已关闭,或者该用户已为您的应用拦截获取后台功能。要处理这种情况,您的应用程序和服务器上还需要更多的逻辑。 你可以做的是在服务器端存储所有发送的未决通知。一旦用户设备上的应用程序收到和解析通知(调用didReceiveRemoteNotification
),您将向服务器发出一个新的呼叫,要求从待处理的数据库中删除通知。最后,在您的应用程序启动时实施一个致电您的服务器的请求,以便在您的应用程序被终止或设备关闭的情况下,当用户再次打开该应用程序时,他将收到所有通知错过。您还可以在服务器上设置一个计时器,以每x天/每小时再次发送一次通知(这并不是真正的建议,您不希望用户因为垃圾邮件而删除您的应用)。
也像其他人所说的那样,信任你的服务器应该在你的徽章上显示的数字比通知本身更好。上面的逻辑用于最近正在处理的类似Tinder的应用程序,以显示用户有多少匹配;)
你可以在服务器的通知载荷中传递''badge“:count',不会那么做吗? –
@BhumitMehta:问题是,在这种情况下,didReceiveRemoteNotification永远不会从我们获取有效负载的位置调用,因为我没有打开通知。 – Nitish
是的,但是如果通知有效载荷包含非0值的“徽章”键,徽章应自动设置。 –