无声推送未在iOS 11上传送到应用程序

问题描述 投票:149回答:13

我注意到在iOS 11 beta 2上,无论应用程序的状态如何(背景/前景),都不会将静默通知传递给application:didReceiveRemoteNotification:fetchCompletionHandler

我实施了UIApplicationDelegete方法application:didReceiveRemoteNotification:fetchCompletionHandler,我发送以下静音推送

{  
  "aps": {  
    "content-available": 1  
  },  
  "mydata": {  
    "foo": "bar"  
  }  
} 

但是在iOS 11上没有调用委托方法。

它在其他版本的iOS上工作正常,文档部分Configuring a Silent Notification没有提到应该做的任何其他事情。

这是iOS 11中的错误还是我错过了iOS 11中的新功能?

请注意,我不是在讨论或使用UserNotification框架,它不需要发送静音推送。

这是一个说明问题的sample project(您必须设置自己的包ID)

当您在示例项目中午餐并将上述有效负载发送到应用程序时,您可以使用macOS控制台查看推送是否正确传递到设备但不是应用程序。

UPDATE 10.08

看来行为是随机的。有时在重新启动设备后,有效负载会正确传送,但一段时间后它会停止工作。

正如您在下面的屏幕截图中看到的那样,标记为1的推送仅传送到设备,推送2(设备重启后)也会传送到应用程序。

enter image description here

UPDATE 14.08 - iOS 11 Beta 6

还是一样的行为。应该起作用的另一件事但不是以下。当应用程序的方案设置为“等待可执行文件启动”时,静音推送应该唤醒应用程序并在后台启动它。

enter image description here

UPDATE 21.08 - iOS 11 Beta 7

在错误报告中仍然是Apple的相同行为而不是更新。

UPDATE 29.08 - iOS 11 Beta 8

仍然是同样的问题。我现在使用的重现步骤如下:

  • 在Xcode项目方案中,选择“等待可执行文件启动”
  • didReceiveRemoteNotification: fetchCompletionHandler中添加断点
  • 在设备上启动应用
  • 发送上面的静音推送

预期:应用程序从暂停状态进入后台并调用didReceiveRemoteNotification: fetchCompletionHandler

实际:没有任何反应

UPDATE 06.09 - iOS 11 Beta 10

我仍然有同样的马车行为。来自Apple的门票更新了以下答案:

Apple Developer Relations 2017年9月6日,下午10:42关于此问题,Engineering提供了以下反馈:

我们能够运行示例应用程序并测试行为。当我们按照描述进行测试时,我们没有看到任何问题。

当应用程序在后台运行时,不保证推送到应用程序,这里的日志表明我们不相信应用程序的使用足以启动它。

我们确实看到我们在条件良好时不时提供推动。

我们相信这是正确的行为。

Update 11.09

我的Apple bug报告已关闭,并标记为33278611的副本,该报告仍然开放

UPDATE 13.09 - iOS 11 GM

感谢kam800的评论(见下文),我做了更多测试并得出了这些观察结果:

在iOS 11 dasd DuetActivitySchedulerDaemon中似乎有一个新的守护进程要么完全丢弃数据推送,要么延迟数据推送:

Delivery postponed

控制台日志

default 13:11:47.177547 +0200   dasd    DuetActivitySchedulerDaemon CANCELED: com.apple.pushLaunch.net.tequilaapps.daylight:C03A65 <private>!   lifecycle   com.apple.duetactivityscheduler
default 13:11:47.178186 +0200   dasd    DuetActivitySchedulerDaemon Removing a launch request for application <private> by activity <private>   default com.apple.duetactivityscheduler
default 12:49:04.426256 +0200   dasd    DuetActivitySchedulerDaemon Advancing start date for <private> by 6.5 minutes to Wed Sep 13 12:55:31 2017   default com.apple.duetactivityscheduler
default 13:21:40.593012 +0200   dasd    DuetActivitySchedulerDaemon Activity <private>: Optimal Score 0.6144 at <private> (Valid Until: <private>)  scoring com.apple.duetactivityscheduler
default 13:21:40.594528 +0200   dasd    DuetActivitySchedulerDaemon Setting timer (isWaking=1, activityRequiresWaking=0) between <private> and <private> for <private>  default com.apple.duetactivityscheduler

推迟交货问题

  • 当数据推送传递被推迟并且应用程序启动时,仅在达到交付日期时才传递数据推送,该日期可能是将来的几分钟。这完全打败了使用数据推送来保持新应用内容为下次发布做好准备的目的。我再次在这里引用Apple的文档:

“无声通知可以帮助您保持应用程序的最新状态,即使它没有运行,也能改善用户体验。”

  • 当两个数据推送发送到暂停的应用程序时,它们会被iOS 11推迟,而不是直接唤醒应用程序。达到交货时间时,仅交付最后一次数据推送!之前的推送丢失,并且未通过委托方法传递,从而导致数据丢失。

Delivery cancelled

控制台日志

default 13:35:05.347078 +0200   dasd    DuetActivitySchedulerDaemon com.apple.pushLaunch.net.tequilaapps.daylight:C03A65:[
    {name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Must Not Proceed, Score: 0.00}}
 ], FinalDecision: Must Not Proceed}    scoring com.apple.duetactivityscheduler

取消交货问题

那么在这种情况下,数据推送完全丢失,并且在iOS 11上正确传送时从未在iOS 11上传送。

UPDATE 19.09 - iOS 11 GM

我还注意到,当应用程序在前台并且通知未发送到应用程序时,我在控制台中看到以下日志:

default 08:28:49.354824 +0200   apsd    apsd    <private>: Received message for enabled topic '<private>' onInterface: NonCellular with payload '<private>' with priority 10 for device token: NO   courier-oversized   com.apple.apsd

fault   08:33:18.128209 +0200   dasd    Foundation  <NSXPCConnection: 0x151eee460> connection from pid 55: Exception caught during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
Exception: value for key 'NS.objects' was of unexpected class 'NSNull'. Allowed classes are '{(
    NSArray,
    NSData,
    NSString,
    NSNumber,
    NSDictionary,
    NSUUID,
    _DASActivity,
    NSSet,
    _DASFileProtection,
    NSDate,
    NWParameters,
    NWEndpoint
)}'.    general com.apple.foundation.xpc
ios push-notification ios11
13个回答
29
投票

所以iOS 11.1 beta 1的发行说明说

iOS 11.1 beta 1刚刚发布,他们提到:“通知已解​​决的问题•更频繁地处理静默推送通知。(33278611)

我做了一些测试,似乎确实修复了:

Suspended State

当我以暂停模式启动应用程序并发送静音推送时,应用程序将返回到后台并调用didReceiveRemoteNotification:fetchCompletionHandler代理。

Foreground State

同样,当应用程序处于前台并发送静默推送时,代理似乎按预期调用。这在以前的iOS 11版本中随机无效,因此我将在更多测试后确认这一点。


1
投票

所以这确实是iOS 11中的一个错误,它现在已经在iOS 11 beta 3中得到修复。现在,当在前台或后台接收静音推送时,application:didReceiveRemoteNotification:fetchCompletionHandler被正确调用。

UPDATE

不,它没有修复,仍然在iOS beta 3和4中发生


1
投票

在写这个答案时,我面临与Bill Dunay's回答完全相同的问题。

我的要求是当应用程序处于前台时接收静默通知,而当应用程序处于后台/未运行时则不接收任何内容。我的解决方法就是这个。我不使用徽章因此将其设置为零对我来说不是问题。

{
    "aps" : {
        "badge" : 0,
        "sound" : ""
    },
    "mydata": {  
        "foo": "bar"  
    }  
}

请注意我故意不使用“内容可用”。设置导致iOS优化逻辑启动延迟/取消通知的传递。


1
投票

我收到了一些通知(不一定是沉默)的问题。

在查看了所有更新和答案后,我可以添加两个可能有用的更新:

  • 我发现在接收通知时访问UIApplication.shared.isRegisteredForRemoteNotifications方法会导致应用程序停止而不向Xcode报告任何内容。收到访问该方法的通知后,请检查您是否正在运行某些代码。 (isRegisteredForRemoteNotifications locking UI with semaphore_wait_trap)。 我发现我在控制台上有一个推送通知解析错误,因为"title-loc-args" : [3333]不接受3333字面意思但接受它作为字符串"title-loc-args" : ["3333"]。这使我的整个界面在我访问上面的方法后停止,仅在iOS 11上,它适用于iOS 12。
  • 我还发现,使用完全相同的代码,它在iOS 12.0(16A5366a)上没有任何问题。但是在iOS 11上它正在发生。

0
投票

在我的情况下,无声通知用于在服务器站点上完成作业后更新ui,因此在应用程序中包含不相关的内容很麻烦。因为我们用于静默通知的有效负载甚至包含标题和正文,所以我实现了这些方法以在活动/非活动应用程序中获取工作通知,而不是充电并且关闭后台应用程序刷新甚至处于低功耗状态。

为了实现这一点,我添加了委托并使用UNUserNotificationCenterDelegate协议和willPresent notification(iOS 10+)方法创建扩展,每次使用正确的有效负载时都会触发该方法。要在应用处于活动状态时不显示通知,请使用徽章或声音呼叫完成。我最终得到了类似的东西

    import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    // MARK: - Lifecycle
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        return true
    }

    //this was only method to handle notifications before
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        //process silent notification
        completionHandler(UIBackgroundFetchResult.newData)
    }
}

extension AppDelegate : UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        //proces notification when app is active with `notification.request.content.userInfo`
        if UIApplication.shared.applicationState == .active {
            completionHandler(.badge)
        }else {
            completionHandler(.alert)
        }
    }
}

当应用程序处于后台并且无声通知不调用我的方法时,为了使这些状态工作,我直接通过applicationDidBecomeActive从通知中心收到通知:

UNUserNotificationCenter.current().getDeliveredNotifications { (notifications) in
            debugLog(message: "unprocessed notification count: \(notifications.count)")
            if notifications.count > 0 {
                notifications.forEach({ (notification) in
                    DispatchQueue.main.async {
                        //handle `notification.request.content.userInfo`
                    }
                })
            }
        }

16
投票

我只想在这里加上我的2美分,因为我也受到了这个问题的打击而且我注意到苹果公司在这个问题上已经关闭了几个雷达表示他们无法重现。我发现一个有趣的事情是,如果应用程序在连接到调试器的同时进行后台处理,则会推送推送。

如果我杀了调试器,请拔掉我的手机,启动应用程序,然后发送静音推送有效负载,我看到应用程序没有被唤醒。我确实在控制台日志中看到系统取消了将负载传送到我的应用程序。

我已经提交了一个带有小样本应用程序的雷达,可以重现问题。我还在雷达中明确指出,在我的机票上工作的人不得运行连接到调试器的应用程序来重现问题。这是链接:https://bugreport.apple.com/web/?problemID=34461063

希望这将在这个问题上取得一些进展。


11
投票

看起来像iOS 11的新行为.iOS 11 beta 10提供了有关此问题的一些描述性日志:

default 23:18:51.806011 +0200   dasd    com.apple.pushLaunch.com.acme.Acme:F7E7D0:[
    {name: ApplicationPolicy, policyWeight: 50.000, response: {Decision: Can Proceed, Score: 0.50}}
    {name: BatteryLevelPolicy, policyWeight: 1.000, response: {Decision: Can Proceed, Score: 0.87, Rationale: [{batteryLevel == 62}]}}
    {name: DeviceActivityPolicy, policyWeight: 5.000, response: {Decision: Can Proceed, Score: 0.20}}
 ] sumScores:52.279483, denominator:81.410000, FinalDecision: Can Proceed FinalScore: 0.642175}
default 23:18:51.806386 +0200   dasd    'com.apple.pushLaunch.com.acme.Acme:F7E7D0' has compatibility score of 1.000000 with 'com.apple.CFNetwork-cc-111-79:E7272D'. Relaxing scores.
default 23:18:51.806855 +0200   dasd    'com.apple.pushLaunch.com.acme.Acme:F7E7D0' CurrentScore: 0.642175, ThresholdScore: 0.738454 DecisionToRun:0

看起来每个静音推送都会传送到iOS,但是dasd守护程序使用几个策略来决定是否应该向应用程序传送静音推送(例如电池电量)。昨天晚上我设法接受了一次静音推送,但当时我的iPhone已连接到充电器 - 可能是BatteryLevelPolicy得分高到足以接受那个静音推送。

Apple没有提供有关此iOS端行为的官方信息,只有关于服务器端限制的信息:

静音通知并不意味着让您的应用程序在后台保持清醒,也不是用于高优先级更新。 APN将无声通知视为低优先级,如果总数过多,可能会完全限制其传递。实际限制是动态的,可以根据条件进行更改,但尝试不要每小时发送多个通知。

我保持手指交叉,他们改变了这种行为,因为这会修复我的应用程序:)另一方面,这种变化很好 - 许多事情之一使iPhone电池持续时间比Android手机更长。


7
投票

iOS 11.1 beta版发行说明包括:通知已解决的问题更频繁地处理无提示推送通知。 (33278611)


6
投票

Apple Developer Relations刚刚在我的雷达上添加了评论:

我们相信此问题已在最新的iOS 11.2测试版中得到解决。

请使用最新的iOS测试版进行测试。如果您仍有问题,请使用可帮助我们调查的任何相关日志或信息更新您的错误报告。

https://developer.apple.com/download/

目前正在安装iOS 11.2 beta - 将测试静默推送行为


5
投票

iOS 11.1 Beta 2也包含

Notifications
Resolved Issues
• Silent push notifications are processed more frequently. (33278611)

在发行说明中 - 将立即测试它。

更新 - 11.10.2017 - iOS 11.1 Beta 2

在“真实场景”中使用我们的应用程序2天后,看起来这个版本的iOS有了真正的改进。我小心翼翼地开始相信这是固定的。


3
投票

iOS 11.4.1,Swift 4

我遇到了无法到达的问题(来自CloudKit),我尝试了所有人在这里提到的一切。然后我决定尝试将空白alertBody设置为我的CKNotificationInfo()对象,如下所示:

let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
info.alertBody = ""

这使得推送以更高的优先级发送(但它们仍然是静默推送)并且我的设备日志中不再出现错误推送被忽略的错误。

我希望能有所帮助。 :)


2
投票

我的应用程序有类似的问题,直到iOS 10我得到推送通知和application:didReceiveRemoteNotification:fetchCompletionHandler被正确调用。但更新到iOS 11推送通知停止工作。

我的代码问题是,即使我在推送通知有效负载中使用content-available:1和mutable-content:1,也没有打开Background Fetch选项。但它在iOS 10之前完美运行。

Make sure you turned ON both these capabilities.

在将背景提取功能打开后,它正在工作


2
投票

作为一种解决方法我们正在添加“通知”键并在“标题”中添加空字符串作为值。这是唤醒appDelegate中的didReceive回调。

© www.soinside.com 2019 - 2024. All rights reserved.