【问题标题】:Update badge with push notification while app in background在后台应用程序时使用推送通知更新徽章
【发布时间】:2012-12-24 18:21:27
【问题描述】:

当应用程序被带到前台时,我已经开始推送通知并设法更新图标徽章计数。

不过我对此有点困惑……iPhone 收到通知,弹出消息似乎激活了我的应用程序,并且徽章仅在我启动应用程序后更新。

就用户体验而言,这听起来不太对劲。我的理解是,徽章计数应该通过增加计数来通知用户需要采取的行动,但这要等到应用程序上线后才会发生。

那么有没有办法告诉应用在收到推送通知时以及在后台时更新其徽章计数?

请注意,我的应用不使用位置信息,并且我在通知注册请求中有UIRemoteNotificationTypeBadge

【问题讨论】:

    标签: ios apple-push-notifications


    【解决方案1】:

    由于推送通知由 iOS 而非您的应用处理,因此您无法在收到推送通知时更改应用程序徽章。

    但您可以在推送通知的有效负载中发送徽章编号,但您必须在服务器端进行计算。

    您应该阅读Local and Push Notification Programming Guide,尤其是The Notification Payload

    有效载荷可能如下所示:

    {
        "aps" : {
            "alert" : "You got your emails.",
            "badge" : 9
        }
    }
    

    现在应用程序徽章图标将显示 9。

    【讨论】:

    • 我已经这样做了...但是只有当我的应用程序被带到前台时才会检索到这个值,我稍后会使用 [UIApplication sharedApplication].applicationIconBadgeNumber = count; 来更新徽章值。
    • 不,您需要在推送通知负载中设置徽章编号。
    • 我再次查看了我的有效负载结构,似乎我将徽章参数的值作为字符串 '4' 而不是 int 4 传递!现在我得到了它的工作......感谢您的帮助
    • @wod 你是什么意思:改变有效载荷结构徽章。
    • 实际上在 iOS 10 中,应用端完全支持这一点。请参阅下面的答案。 stackoverflow.com/a/53159748/2223756
    【解决方案2】:

    实际上在 iOS 10 中,远程 Notification 会自动调用 AppDelegate 中的 didReceiveRemoteNotification 方法。

    您有两种在后台更新徽章计数的方法。
    我也为我当前的应用程序做了这个。您也不需要通知服务扩展。

    第一种方式:

    将 APS 徽章密钥与您的有效负载一起发送到 APN。
    这将根据您的徽章有效负载中的整数值更新徽章计数。例如:

    // Payload for remote Notification to APN
    {
        "aps": {
            "content-available": 1,
            "alert": "Hallo, this is a Test.",
            "badge": 2, // This is your Int which will appear as badge number,
            "sound": default
        }
    }
    

    第二种方式:

    当 applicationState 为 .background 时,您可以切换您的 application.applicationState 并更新您的徽章计数。但是当发送到 APN e.x. 时,您必须注意不要在通知负载中设置徽章密钥参数。

    // Payload to APN as silent push notification
    {
        "aps": {
            "content-available": 1
        }
    }
    

    根据应用状态处理徽章更新:

    这是我在 APN 的有效负载中没有徽章密钥的徽章计数更新的工作代码。

    func application(_ application: UIApplication, didReceiveRemoteNotification 
       userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("APN recieved")
        // print(userInfo)
        
        let state = application.applicationState
        switch state {
            
        case .inactive:
            print("Inactive")
            
        case .background:
            print("Background")
            // update badge count here
            application.applicationIconBadgeNumber = application.applicationIconBadgeNumber + 1
            
        case .active:
            print("Active")
    
        }
    }
    

    重置徽章计数:

    当您的应用恢复活动状态时,不要忘记重置您的徽章计数。

    func applicationDidBecomeActive(_ application: UIApplication) {
        // reset badge count
        application.applicationIconBadgeNumber = 0
    }
    

    【讨论】:

    • 如果应用不在后台运行,如何更新徽章?
    • 如果您发送带有内容可用密钥的 APS,无论应用程序的状态如何,它都会运行 didReceiveRemoteNotification 方法。只需使用本机设备尝试一下。如果您使用的是 iOS,则可以使用此工具将您的 JSON 对象发送到 APN:github.com/noodlewerk/NWPusher
    • 哇,太好了,如果我发送的通知没有内容可用怎么办? (这是关于任何非背景通知)。 didReceiveRemoteNotification 未被调用
    【解决方案3】:

    我们可以通过在推送通知包中发送"badge"参数来更改后台状态下的徽章编号。正如@rckoenes 指出的,徽章的JSON 参数必须是INTEGER

    执行相同操作的示例 PHP 代码

    // Create the payload body
    $body['aps'] = array(
            'alert' => $message,
            'badge' => 1,
            'sound' => 'default'
            );
    

    badge => 1 其中 1 是整数而不是字符串(即没有撇号)

    【讨论】:

      【解决方案4】:
          **This is the APNS payload get back from server.**
      
          {
              "aps" : {
                  "alert" : "You got your emails.",
                  "badge" : 9,
                  "sound" : "bingbong.aiff"
              },
              "acme1" : "bar",
              "acme2" : 42
          }
      

      键徽章的值自动被视为徽章计数。在 ios 应用端无需计算或处理计数。 在上面的示例中,9 是徽章计数。因此您的应用图标将显示为 9。

      注意当您的应用程序关闭时,您无法自行处理徽章。这就是我们使用 APNS Payload 中的徽章密钥的原因 有关通知的更好说明,请参阅文档

      如果你想自己减少徽章数量。减少数量并自己更新。如下

      【讨论】:

        【解决方案5】:

        如果您使用的是 NotificationServiceExtension,您可以在其中更新徽章。

        var bestAttemptContent : UNMutableNotificationContent? // 
        bestAttemptContent.badge = 0//any no you wanna display
        

        每次您的应用程序收到通知时,您的服务扩展都会被调用。将该值保存在用户默认值中并显示它。 要在应用程序和扩展程序之间共享用户默认值,您需要在应用程序中启用应用程序组。 Read more here

        【讨论】:

        • 您可以将该通知计数保存在服务器上并与通知一起发送。
        • 我用的是 Firebase 云消息,你知道怎么做吗?
        【解决方案6】:

        从 iOS 10 开始,您可以为您的应用开发通知服务扩展。当您收到通知时系统会启动它,您可以为徽章计算一个有效的数字并设置它。

        查看文档: https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension

        【讨论】:

          【解决方案7】:

          对于 Firebase 云消息传递 (FCM),它应该是这样的:

          {
            "to": "some_token",
          
            "notification": {
              "body": "this is a body",
              "title": "this is a title",
              "badge" : 1
            }, 
          
            "priority": "high", 
          }
          

          【讨论】:

            【解决方案8】:
            -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
            
                application.applicationIconBadgeNumber = 0;
                NSLog(@"userInfo %@",userInfo);
            
                for (id key in userInfo) {
                    NSLog(@"key: %@, value: %@", key, [userInfo objectForKey:key]);
                }
            
                [application setApplicationIconBadgeNumber:[[[userInfo objectForKey:@"aps"] objectForKey:@"badge"] intValue]];
                NSLog(@"Badge %d",[[[userInfo objectForKey:@"aps"] objectForKey:@"badge"] intValue]);
            }
            

            【讨论】:

            • 你为什么使用intValue而不是NSInteger的integerValue? @property (readonly) NSInteger integerValue NS_AVAILABLE(10_5, 2_0);
            【解决方案9】:

            正如@rckoenes 所说,您必须在服务器端进行计算,但是您怎么知道何时增加您应该在有效负载中发送的徽章编号值呢?

            当您启动应用程序时,是否会向您的服务器发送一条消息,表明应用程序已启动。因此,在服务器端,您从徽章 = 0 重新开始,虽然服务器没有收到任何消息,但随着每个推送通知有效负载增加徽章编号。

            【讨论】:

              【解决方案10】:

              在 apns 有效负载中必须定义 "content-available":1 以在后台模式下更新徽章计数

              func application(_ application: UIApplication, didReceiveRemoteNotification 
                 userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
              
              
              // increase badge count, but no need if you include content-available
              
              application.applicationIconBadgeNumber = application.applicationIconBadgeNumber + 1
              
              }
              
              func applicationDidBecomeActive(_ application: UIApplication) {
              
              // reset badge count
              
              application.applicationIconBadgeNumber = 0
              
              }
              

              例如。

              "aps":{
                  "alert":"Test",
                  "sound":"default",
                  "content-available":1
              
              }
              

              【讨论】:

              • content-available = 1 的目的是静默通知而不是徽章。
              【解决方案11】:

              在其工作中,“徽章”集计数

              {
                "to": "token",
                "notification": {
                  "title": "Example",
                  "body": "Tiene 22 actualizaciones.",
                  "badge":278
                },
                "data": {
                  "story_id": "story_12345",
                  "count_vaca":22
                }
              }
              

              【讨论】:

                【解决方案12】:

                打开App收到远程通知后,

                在您的AppDelegate 的“didBecomeActive”方法中获取当前徽章编号。

                使用以下代码文件:

                int badgeCount = [UIApplication sharedApplication].applicationIconBadgeNumber;
                    badgeCount = badgeCount + 1;
                

                【讨论】:

                • 在用户点击应用程序或通知启动应用程序之前,这将不起作用。它不会做 OP 想要做的事情,即在应用程序处于后台并且 用户与应用程序或通知交互之前更新徽章。
                猜你喜欢
                • 1970-01-01
                • 2014-07-18
                • 1970-01-01
                • 1970-01-01
                • 2019-09-06
                • 2017-12-02
                • 1970-01-01
                • 2015-10-25
                • 2021-11-17
                相关资源
                最近更新 更多