首页 文章

仅在设备正在充电和/或应用程序是前台时才会发送静音推送通知

提问于
浏览
51

我已经实现了静默推送通知,但我注意到了一些奇怪的行为 . 静默推送通知通过以下方式处理:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

如果设备正在充电(即连接电缆)和/或我的应用程序是前台,则似乎只接收静音推送消息 .

如果我断开设备与充电器(或Mac)的连接,则除非应用程序是前台,否则不再接收静音推送通知 .

在这两种情况下,我都会得到非静音推送通知 .

如果我再次插入USB电缆,那么无论应用程序是前景还是后台,我都会收到预期的行为并收到静音推送通知 .

我正在使用UILocalNotification,所以我知道收到了什么 .

连接设备一切正常的事实表明我的静音推送通知配置正确,并且应用程序具有在plist中设置的正确背景模式等 .

在iPhone 5s,6和iPad 2上都可以重复此行为,所有这些都运行IOS 8或8.1 .

还有其他人经历过这个吗?它应该很容易重现 . 为什么将设备插入充电器的简单行为会改变接收静音推送通知的能力?

8 回答

  • 2

    它不起作用,因为您在plist中启用了错误的背景模式 . 您需要启用 remote-notification 标记(应用程序下载内容以响应推送通知),而不是提取 . Fetch用于其他东西 . 您可能还需要使用JSON有效内容中的内容可用密钥,例如,

    {
       "aps": {
          "content-available": 1
        },
        "yourdatakey":{data}
    }
    
  • 0

    我们遇到了相同的行为,并一直试图理解为什么iOS决定提供一些通知而不是其他通知 .

    到目前为止我们所做的是:

    • 当在wifi上然后在蜂窝数据上时,将在后台更可靠地接收消息 . 事实上,当在蜂窝网络(3g / 4g)上时,如果您的信号强度不够强,iOS会收到推送消息,但不会唤醒您的应用 . 我们在这里发布了关于它的苹果论坛:https://devforums.apple.com/message/1069814#1069814 . 我们还开了一张支持票,支持团队告诉我们把它作为一个错误报告提交给我们,我们几周前做过这个报告,现在还在等待回复 .

    • 当您收到推送消息时,您需要尽快调用fetchCompletionHandler . 从技术上讲,你有30秒的时间来执行后台处理,但iOS有一个公式,你发送推送消息的次数越多,并且根据你在将应用程序恢复到暂停状态之前处理这些消息所花费的时间,iOS可以减少金额你的应用程序将来被唤醒的时间 .

    Apple didReceiveRemoteNotification:fetchCompletionHandler:文档中可以看到这里:

    完成处理通知后,必须在处理程序参数中调用块,否则您的应用程序将被终止 . 您的应用程序有最多30秒的挂钟时间来处理通知并调用指定的完成处理程序块 . 实际上,您应该在处理完通知后立即调用处理程序块 . 系统会跟踪应用程序后台下载的已用时间,功耗和数据成本 . 处理推送通知时使用大量电源的应用可能无法提前唤醒以处理将来的通知 .

    在我们的测试中,我们一直在向我们的应用发送频繁的静音推送通知(每10到30秒) . 在我们让它重新入睡之前,应用程序已经醒了大约3秒钟 . 随着时间的推移,我们已经注意到我们的应用程序被唤醒的频率已经降低到iOS只会每15到30分钟唤醒应用程序的程度 . 因此似乎存在某种衰减/限制公式,但我们找不到任何关于它如何正常工作的文档 . 我们已经请求此公式和来自apple的变量作为支持请求,但他们说“您要求的信息不公开”,并再次要求我们提交错误报告 .

    那么,希望这有用吗?我们仍在努力学习更多自己,这就是我发现这个问题的原因:)

  • 0

    随着iOS8背景推送到应用程序已发生变化 . 现在,只有在某些情况下才会将后台推送到应用程序 . Apple没有明确说明这些情况究竟是什么,但是从我的广泛实验来看,它基本上归结为手机是否正在充电 . 还有一些其他变量在起作用(例如网络类型,设备类型,启用了wifi),但主要的主要因素是当推送到达时设备是否正在充电 .

    如果通过直接主电源为手机充电,或者通过USB连接到计算机,则通过后台进行间接充电推送将在绝大多数时间内传递给应用程序 . 但是,断开手机与电源或USB的连接,即使手机的电池100%充电,也几乎不会将背景推送到应用程序 .

    您可以非常轻松地为自己测试这一点,只需在手机充电时发送一些推送而不是手机充电 . 但是你必须考虑到后台推动开发构建和使用沙箱环境不要与 生产环境 构建和 生产环境 环境的后台推送相同,后台推送实际上更有可能在开发中传递给应用程序那么他们正在 生产环境 中,因此使用 生产环境 版本和Apple的 生产环境 环境进行测试以查看实际结果至关重要 .

    注意推送传递有两个步骤,第一步是它需要传送到手机本身,第二步是手机拥有它,然后需要由操作系统传送到应用程序 . 在iOS7中,诸如Tifi on Wifi之类的东西使推动电话增加的机会增加了 . 使用iOS8,即使推送成功传送到手机,如果手机没有充电,操作系统也不会将其转发到后台应用程序 . 这意味着手机会收到通知并保留通知,有时持续几个小时,如果手机没有收费,它可能会转发给应用程序 .

  • 9

    我遇到了同样的问题以及在应用程序未充电时未接收推送通知的原因是当从 Settings > Battery 启用低功耗模式时,它会禁用所有应用程序的 background-fetch 功能 .

    这会阻止设备接收推送通知 .

    此链接可能有用 . Apple Documentation

  • 58

    我也注意到了同样的事情并浪费了一些时间来搞清楚 . 见https://stackoverflow.com/a/31237889/1724763

    如果您关闭了Bg App Refresh,静音远程推送将被静默删除(具有讽刺意味) .

    但是,我的观察是,如果您通过电缆连接到Xcode,则会忽略Bg App Refresh设置,并且您的应用程序的所有静音推送都可以正常工作 .

    我非常怀疑这是一个没有记录的功能:充电会导致Bg App Refresh设置被忽略 .

  • 1

    我希望您使用 APNS 提供优先级为 "CONSERVE_POWER" (5) ,尝试将其更改为 "IMMEDIATE" (10)

  • 5

    我've been experiencing this problem for some time, and am very grateful for this question and @Kevin D. sharing their understanding. I'我开始认为https://stackoverflow.com/a/30834566/1449799https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW4(参见其中一个表中的 priority )描述了我的应用程序遇到问题的原因:

    将此优先级用于仅包含内容可用密钥的推送是错误的 .

    要发送通知,我正在使用node-apn默认情况下(我也需要)将优先级设置为max( 10 [注意,此时看起来只有 105 是正确值]),但是因为我想要一个无声的通知,我没有 alertbadgesound 设置 .

  • 7

    我找到了另一个使用PushKit Framework为我工作的解决方案

    VoIP推送在VoIP应用程序所需的标准推送之上提供附加功能,以便在向用户显示通知之前执行推送的按需处理

    当我发送VOIP推送时,应用程序会唤醒应用程序的任何状态并执行任何操作

    在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服务证书的证书

    enter image description here

相关问题