如果应用程序未运行时收到推送通知,它们将会消失。

4
我正在开发一个应用程序,可以接收推送通知,在某些情况下会触发后台获取操作。因此,我已经为我的应用程序启用了remote-notification后台功能。
当应用程序处于挂起状态时,推送通知会使应用程序唤醒并执行application:didReceiveRemoteNotification:fetchCompletionHandler,横幅出现在主屏幕上,并且通知保留在通知中心中,直到用户点击它以启动应用程序。它的工作方式完全符合预期。
当应用程序未运行时,只要没有被用户强制退出(请参见苹果文档),通知就会启动应用程序,并执行application:didFinishLaunchingWithOptionsapplication:didReceiveRemoteNotification:fetchCompletionHandler。横幅出现在主屏幕上,但是通知随后消失了。它不会保留在通知中心中。此外,如果设备被锁定,有时通知甚至在完成警报声之前就消失了。
有趣的是,如果我禁用远程通知后台模式,一切都正常。在这种情况下,推送通知到达时不会启动应用程序。
当远程通知后台模式开启且接收到通知启动未运行的应用程序时,我该如何防止通知消失?我需要在application:didFinishLaunchingWithOptions中包含什么内容,让应用程序知道它正在后台启动,并且不应丢弃通知吗?

你是否在 application:didReceiveRemoteNotification:fetchCompletionHandler: 方法中正确调用了完成处理程序? - rmaddy
是的,不是那个问题。我实际上刚刚找到了问题所在。我一有时间就会发布答案。基本上,我的 application:didFinishLaunchingWithOptions 有一行代码使用了我正在使用的 SDK(Kinvey)来注册推送。我不知道具体发生了什么,但当它被调用时,应用程序似乎重新注册了推送,并且丢弃了传入的推送。因此,我写了几行代码来避免在后台启动应用程序时调用它,这解决了问题。 - ConfusedByCode
3个回答

4
似乎是因为当应用在后台启动并执行application:didFinishLaunchingWithOptions:时,它会重新注册远程通知,导致推送通知消失。重新注册似乎会丢弃任何排队的消息。

我的解决方案是,在调用推送注册方法之前检查应用是否由于推送通知而在后台启动。我正在使用Kinvey SDK,因此以下代码使用了Kinvey的方法,但我强烈怀疑这个解决方案也适用于其他推送注册方法,包括标准的UIApplication.registerForRemoteNotifications

导致问题的代码是:

func application(application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
    // Initialize Kinvey SDK singleton
    KCSClient.sharedClient().initializeKinveyServiceForAppKey("myappid",
        withAppSecret: "mysecret",
        usingOptions: nil)

    KCSPush.registerForPush()
    // rest of method...
}

通过将其更改为以下内容,我解决了这个问题:

func application(application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
    // Initialize Kinvey SDK singleton
    KCSClient.sharedClient().initializeKinveyServiceForAppKey("myappid",
        withAppSecret: "mysecret",
        usingOptions: nil)

    if let _ = 
        launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {

        let appState: UIApplicationState = UIApplication.sharedApplication().applicationState

        if appState == .Active || appState == .Inactive {
            KCSPush.registerForPush()
        }
    } else {
        KCSPush.registerForPush()
    }
    // rest of method...
}

现在,当一个应用程序通过传入的推送通知被启动到后台时,它不会重新注册推送,并且该通知将一直保留在iOS通知中心中,直到用户点击它或手动启动该应用程序。


啊,谢谢你!我已经为这个问题苦恼了很久。 - irosenb

2

我尝试不注册通知,即使应用在后台,就像这里所建议的答案一样,但对于我来说,它没有解决这个问题。我发现手动设置应用程序徽章号码会导致通知消失。

我在application:didFinishLaunchingWithOptions:中编写了代码,检查用户的状态,并(在其他情况下)将标志图标设置为0,如果没有活跃的用户,则将其设置为我在NSUserDefaults中保存的值。结果,这两行代码中的任何一个都会导致通知几乎立即消失并停止播放通知声音。之所以在随后的推送中没有发生这种情况,是因为didFinishLaunching相当长时间没有再次被调用。


简而言之 - 确保您没有在任何应用程序生命周期方法或didReceiveRemoteNotification中手动设置应用程序徽章图标。如果您的通知仅在第一次接收时消失,请仔细查看didFinishLaunching


2
我发现手动设置应用程序徽章数字会导致通知消失。
不是手动设置徽章数字。它是将徽章数字设置为零。
根据人机界面指南:
保持徽章最新。人们查看相应信息后,立即更新您的应用程序徽章。您不希望人们认为有新信息可用,只发现他们已经看过了。请注意,将徽章计数减少到零会从通知中心中删除所有相关通知。

https://developer.apple.com/design/human-interface-guidelines/ios/system-capabilities/notifications/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接