繁体   English   中英

UIBackgroundRefreshStatusDenied 未发送静默推送通知,但应用程序在前台

[英]Silent push notification not delivered with UIBackgroundRefreshStatusDenied but app in foreground

使用UIBackgroundRefreshStatusAvailable ,我的应用程序按预期接收静默推送通知,无论是在后台还是在前台。

此功能的名称——后台应用程序刷新——向我表明它在禁用时不会影响前台应用程序的行为。

不幸的是,我的应用程序在前台时没有收到静默推送通知,后台应用程序刷新被禁用,即UIBackgroundRefreshStatusDenied

我没有使用用户可见的推送通知,因此不涉及UNUserNotificationCenter等。

是否可以在禁用后台应用刷新的情况下接收静默推送通知,即UIBackgroundRefreshStatusDenied

Objective-C,Xcode 11.3.1,部署目标 iOS 10.3。 安装了 iOS 12.4.5 的 iPhone 6。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [application registerForRemoteNotifications];
    return YES;
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    // not called when app in foreground but bg app refresh turned off
}

这是启用 bg 应用刷新时收到的didReceiveRemoteNotification的示例userInfo dict:

{
aps =     {
    "content-available" = 1;
};
ck =     {
    ce = 2;
    cid = "iCloud.de.udo-thiel.DiskBench";
    ckuserid = "_56bd97c2eb1e52d09756163efaab6b02";
    nid = "e70e4a8d-d77b-4315-8b3e-d9de229cf083";
    qry =         {
        dbs = 2;
        fo = 2;
        rid = "Res-iPad 2-16";
        sid = "public-results2";
        zid = "_defaultZone";
        zoid = "_defaultOwner";
    };
};

}

这是一个有趣的问题,因为它基本上解决了命名这个相当复杂的功能的问题。

总之,恐怕答案是否定的。 虽然我自己不必处理这个问题,但我在同一个 position 中目睹了许多其他人。

对我来说,将整个“静默远程通知功能”视为与应用程序处于前台或后台的关系较小,而与“远程应用程序输入”的关系更大:

如果它被激活,即你有UIBackgroundRefreshStatusAvailable ,你的服务器可以静默地发送它,在这种情况下,消息会做出反应。 基本上,服务器以与用户点击类似的方式提供输入(尽管显然是通过不同的调用函数)。 无论应用程序是在前台还是后台,都会发生这种输入。

如果该功能处于非活动状态,即您有UIBackgroundRefreshStatusDeniedUIBackgroundRefreshStatusRestricted ,则整个功能都已关闭 这意味着这种接收输入的方式不起作用, application:didReceiveRemoteNotification:fetchCompletionHandler:根本没有被调用。 诚然,这个方法名称比 state 枚举案例更好地反映了这个问题。


两种解决方法

  1. 最明显的一个:在applicationDidBecomeActive:applicationWillResignActive:中注册和注销远程通知。 不幸的是,这可能会变得很难看,因为它会导致您的服务器为用户不断更改令牌,但是如果您想不惜一切代价避免在后台收到通知,请使用 go 这种方式。
  2. 注册一次通知,确实让您的逻辑处理前台后台的通知,就像您(似乎)已经做的那样,但只需让它在后台时忽略通知(使用UIApplication.shared.applicationState )。 从技术上讲,这会“浪费”一些运行时间,因为您的应用程序可能会被唤醒,然后不会做任何有意义的事情,但我认为这还不错。

我自己会选择 go 和选项 2,因为我很少看到在后台收到无声通知会很痛苦的情况。

一般来说,我不会做任何依赖于启用通知(后台或前台)的事情。 换句话说:是的,如果我的应用程序在前台并且我需要对服务器上发生的事情做出反应,恐怕我需要“检查”所述服务器,即以某种形式从中提取。

或者我会根据情况通知用户他们应该启用它,否则应用程序将没有多大意义......嗯......


作为旁注:是的,Apple SDK 有点混淆命名和解释所有不同的背景事物和通知。 甚至应用程序 state 本身(活动、非活动、背景、前景、暂停......)也比名称看起来更复杂。 我认为其原因本质上是历史性的。 在我们完全没有后台模式和通知之前,人们只是轮询数据以获得“无声前台通知”之类的东西,基本上就是你想要的东西。 所以最终他们希望在应用程序不在前台时也能做到这一点,大声要求后台执行。 Apple 并不想无限制地授予这一点,所以通知概念发展缓慢,但由于它有点相关,“背景”一词潜入其中(此外,我们也有背景获取......),甚至如果它不一定有意义。 人们也可能会争辩说它仍然是有效的,因为它对于应用程序处于后台/暂停时更为重要。 在前台获得静默通知”的用例仍然可以通过简单的轮询来涵盖(尽管我同意这很丑陋),并且如果您使用推送,也可以在后台获取这些通知。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM