iOS 11上的应用程序未提供无声推送

iOS 11上的应用程序未提供无声推送,ios,push-notification,ios11,Ios,Push Notification,Ios11,我注意到,在iOS 11 beta 2上,无论应用程序的状态如何(后台/前台),静默通知都不会发送到应用程序:didReceiveMemotentification:fetchCompletionHandler 我实现了UIApplicationDelegete方法application:didReceiveEmotentification:fetchCompletionHandler,并发送以下静默推送 { "aps": { "content-available": 1

我注意到,在iOS 11 beta 2上,无论应用程序的状态如何(后台/前台),静默通知都不会发送到
应用程序:didReceiveMemotentification:fetchCompletionHandler

我实现了
UIApplicationDelegete
方法
application:didReceiveEmotentification:fetchCompletionHandler
,并发送以下静默推送

{  
  "aps": {  
    "content-available": 1  
  },  
  "mydata": {  
    "foo": "bar"  
  }  
} 
但在IOS11上不调用委托方法

它可以在其他版本的iOS上正常工作,文档部分没有提到其他任何操作

这是iOS 11中的一个bug还是我错过了iOS 11中的一些新功能

请注意,我不是在谈论或使用
UserNotification
框架,发送静默推送不需要该框架

下面是一个示例,说明了这个问题(您必须设置自己的bundle id)

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

更新10.08 这种行为似乎是随机的。有时,在重新启动设备后,有效负载会正确传递,但过一段时间后会停止工作

正如您在下面的屏幕截图中所看到的,标记为1的推送仅发送到设备,而推送2(在设备重新启动后)也发送到应用程序

更新14.08-iOS 11 Beta 6 还是一样的行为。另一件本应有效但却无效的事情是:。当应用程序的方案设置为“等待可执行文件被启动”时,一个静默推送应该会唤醒应用程序并在后台启动它

更新21.08-iOS 11 Beta 7 仍然是同样的行为,而不是在bug报告中苹果的更新

更新29.08-iOS 11 Beta 8 还是一样的问题。我现在使用的复制步骤如下:

  • 在Xcode项目方案中,选择“等待可执行文件启动”
  • didReceiveEmotentification:fetchCompletionHandler
  • 在设备上启动应用程序
  • 发送上述无声推送
预期:应用程序将从挂起状态带到后台,并调用
DidReceiveMemoteNotification:fetchCompletionHandler

实际的:什么都没有发生

更新06.09-iOS 11 Beta 10 我仍然有同样的行为。来自苹果的票证更新为以下答案:

苹果-开发商关系2017年9月6日晚上10:42工程部 就这个问题提供了以下反馈:

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

推送不保证在应用程序运行时到达应用程序 背景和这里的日志表明我们不相信该应用程序是正确的 被用来发射它

我们确实看到,在条件允许的情况下,我们会时不时地进行推送 好

我们认为这是正确的

更新11.09 我的Apple bug报告已关闭,并标记为保持打开状态的
33278611
的副本

更新13.09-iOS 11 GM 多亏了kam800的评论(见下文),我做了更多的测试并得出了这些观察结果:

iOS 11中似乎有一个新的守护进程,它要么完全放弃数据推送,要么延迟数据推送的传递:

延期交货 控制台日志

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
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
取消交付问题

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
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 10上正确交付

更新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
default 08:28:49.354824+0200 apsd apsd:已收到启用主题“onInterface:Non Cellular with payload”的消息,设备令牌的优先级为10:NO courier oversized com.apple.apsd
故障08:33:18.128209 + 0200 DASD基础连接从PID 55:在接收到的消息的解码过程中捕获异常,丢弃传入消息。
异常:解码参数0时异常(调用的#2):
异常:键“NS.objects”的值属于意外的类“NSNull”。允许的课程是'{(
恩萨雷,
NSData,
NSString,
NSN编号,
国家统计局字典,
NSUUID,
_DASActivity,
NSSet,
_达斯菲尔保护,
NSDate,
nw参数,
NWEndpoint
)}'.    通用计算机应用程序

所以这确实是iOS 11中的一个bug,现在在iOS 11Beta 3中已经修复。当在前台或后台接收到静默推送时,现在可以正确调用
应用程序:didReceiveMemoteNotify:fetchCompletionHandler

更新


不,它不是固定的,并且仍然在iOS beta 3和4中出现

看起来像是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连接到了充电器上——可能是BatteryLevel策略分数高到足以接受一次无声的推送

苹果没有提供有关iOS端行为的官方信息,只有关于服务器端节流的信息:

静默通知并不是让你的应用保持清醒的方式 背景,也不是用于高优先级更新。APNs 将静默通知视为低优先级,可能会导致
{
    "aps" : {
        "badge" : 0,
        "sound" : ""
    },
    "mydata": {  
        "foo": "bar"  
    }  
}
    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)
        }
    }
}
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`
                    }
                })
            }
        }