无声推送通知仅在设备充电和/或应用程序处于前台时才会提供
我已经实施了无声推送通知,但是我注意到了一些奇怪的行为。 无声推送通知通过以下方式处理:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
只有设备正在充电(即连接电缆)和/或如果我的应用程序是前景,似乎只收到静音推送消息。
如果我将设备与充电器(或Mac)断开连接,则除非应用程序处于前台状态, 否则将不再接收静默推送通知。
在这两种情况下,我都会收到非静默推送通知。
如果我再次插入USB电缆,则会收到预期的行为,无论应用程序是前台还是后台,都会收到无声推送通知。
我正在使用UILocalNotification,所以我知道接收的是什么。
事实上,这一切工作正常与连接的设备表明,我的无声推动通知configuration正确,应用程序具有正确的背景模式设置在plist等。
这种行为在iPhone 5s,6和iPad 2上均可重复,全部运行IOS 8或8.1。
有没有人经历过这个? 应该很容易重现。 为什么将设备插入充电器的简单行为会改变接收静默推送通知的能力?
我们已经经历了相同的行为,并试图了解为什么iOS决定提供一些通知,而不是其他人。
我们到目前为止所做的是:
-
在无线上,然后在蜂窝数据上,消息将在后台得到更可靠的接收。 事实上,在蜂窝networking(3g / 4g)上,如果你的信号强度不够强,iOS会收到推送消息,但是不会唤醒你的应用程序。 我们在苹果论坛发布了关于它的地方: https : //devforums.apple.com/message/1069814#1069814 。 我们还打开了一张支持票,支持小组告诉我们把它作为一个错误报告提交给我们,这个报告是我们几个星期前做的,现在还在等待回复。
-
当您收到推送消息时,您需要尽快调用fetchCompletionHandler。 从技术上讲,你有30秒的时间来执行后台处理,但是iOS已经有了一个公式,你发送推送消息的频率越高,根据你在处理这些消息之前花费的时间,iOS可以减less数量你的应用在未来被唤醒的时候。
从苹果的didReceiveRemoteNotification看到这里:fetchCompletionHandler: documentation:
一旦完成处理通知,您必须在处理程序参数中调用该块,否则应用程序将被终止。 您的应用程序有最多30秒的挂钟时间来处理通知并调用指定的完成处理程序块。 在实践中,您应该在处理通知后立即调用处理程序块。 系统会跟踪您的应用的后台下载的已用时间,用电量和数据成本。 在处理推送通知时使用大量电力的应用程序可能不会总是提前被唤醒以处理未来的通知。
在我们的testing中,我们一直在向我们的应用发送频繁的静默推送通知(每10-30秒)。 应用程序醒了大约3秒钟之后,我们把它放回去睡觉。 随着时间的推移,我们肯定已经注意到我们的应用程序被唤醒的频率下降到iOS每15到30分钟才会唤醒应用程序的时间。 所以似乎有某种衰减/节stream公式,但我们无法find任何有关它如何工作的文档。 我们已经要求这个公式和来自苹果的variables作为支持请求,但他们说:“你所请求的信息是不公开的”,并再次要求我们提交一个错误报告。
那么,希望这有帮助吗? 我们仍然在努力学习更多自己,这就是为什么我发现这个问题:)
随着iOS8后台推送到应用程序已经改变。 现在只能在特定情况下将背景推送到应用程序。 苹果公司并没有明确说明这些情况究竟是什么,但是从我的大量实验来看,基本上归结为手机是否在充电。 还有其他一些variables(比如networkingtypes,设备types,wififunction),但主要的主要因素是推送到达时设备是否正在充电。
如果手机是通过直接的主电源充电,或通过USB连接到计算机间接进行充电,则背景推送将在绝大多数时间被传送到应用程序。 但是断开手机与电源或USB的连接,即使手机的电池电量已经100%充电,背景推送也几乎不会传送到应用程序。
你可以很容易地testing这个自己,只是通过发送一些推,而手机正在充电,而不是。 但是你必须考虑到背景推动开发构build和使用沙箱环境不要像生产构build和生产环境背景推动一样,背景推动实际上更有可能被传递到开发中的应用程序那么他们正在生产,所以使用生产版本和苹果的生产环境来testing实际结果是至关重要的。
请注意,推送function有两个步骤,第一步是需要交付给手机本身,第二步是手机拥有它,然后需要由操作系统交付给应用程序。 在iOS7上,Wifi上的图灵使得手机上网的机会增加。 但是,使用iOS8,即使推送成功地传送到手机,如果手机没有被充电,操作系统也不会将其转发到后台应用程序。 这意味着手机会收到通知,并持续几个小时,如果手机没有被充电,它可能会转发到应用程序。
我遇到过同样的问题,而在应用程序不充电时未收到推送通知的原因是,当从Settings > Battery
启用低功耗模式时,会禁用所有应用程序的background-fetch
function。
这可以防止设备接收推送通知。
这个链接可能是有用的。 Apple文档
这是不行的,因为你在plist中启用了错误的背景模式。 您需要启用remote-notification
标记(应用程序下载内容以响应推送通知),而不是获取。 Fetch被用于别的东西。 您可能还需要使用JSON有效内容中的可用内容密钥,例如,
{ "aps": { "content-available": 1 }, "yourdatakey":{data} }
我也注意到了一样,浪费了一些时间。 请参阅https://stackoverflow.com/a/31237889/1724763
如果您closures了Bg应用程序刷新,静默远程推送将被默默地放弃(具有讽刺意味)。
然而,我的观察是,如果你通过电缆连接到Xcode,不知怎的,Bg应用程序刷新设置将被忽略,所有沉默推送您的应用程序的作品。
我高度怀疑这是一个没有logging的function:充电导致Bg应用程序刷新设置被忽略。
我发现另一个解决scheme,使用PushKit框架为我工作
VoIP推送在标准推送之上提供额外的function,VoIP应用程序在向用户显示通知之前执行推送的按需处理
当我发送VOIP Push应用程序时,会唤醒应用程序的任何状态,并可以执行任何操作
在didFinishLaunchingWithOptions中注册VOIP PushNotification
PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()]; pushRegistry.delegate = self; pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP]; - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{ if([credentials.token length] == 0) { NSLog(@"voip token NULL"); return; } NSString *originalToken=[NSString stringWithFormat:@"%@",credentials.token]; NSString *token = [originalToken stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]]; token = [token stringByReplacingOccurrencesOfString:@" " withString:@""]; NSLog(@"PushCredentials: %@",token);}
那么一旦你收到VOIP PushNotification,你就可以在这个函数中处理任何后台获取
-(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type
注意:您必须使用启用VoIP服务证书的证书
我希望你使用的APNS优先级为"CONSERVE_POWER" (5)
,尝试将其改为"IMMEDIATE" (10)
我已经经历了这个问题一段时间了,非常感谢这个问题和凯文D.分享他们的理解。 我开始认为, https://stackoverflow.com/a/30834566/1449799和https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#/ / apple_ref / doc / uid / TP40008194-CH101-SW4 (请参阅其中一个表中的priority
)正在描述为什么我的应用程序遇到问题:
将此优先级用于只包含
content-available
密钥的推送是错误的。
发送通知,我使用node-apn默认(我也需要)的优先级设置为最大( 10
[当心,看起来只有10
和5
是在这个时候是正确的值]),但因为我想要一个安静的通知,我没有alert
, badge
或sound
集。