IOS 使用 FCM 的数据通知

IOS data notifications with FCM

我正在使用 FCM(firebase 云消息传递)向 IOS 应用发送 "custom" 数据通知。据我了解,当您希望 FCM 代表您的应用处理显示通知时,我们会使用通知消息。当您只想在您的应用程序中处理消息时,我们会使用数据消息。这是设计使然。

我面临的问题是 Device/InstandID 令牌对于已安装的应用程序是唯一的,而不是登录该应用程序的用户。所以为了解决这个问题,我在数据中发送了预期的用户标签,这样它就变成了一条数据消息。由于应用程序处理数据通知,didReceiveRemoteNotification() 回调仅在应用程序打开时触发,并且通知仅在发送时显示而不是立即显示。

我的问题是,我可以发送自定义数据通知消息并让它在应用程序关闭时立即显示吗?

这是我发送给 FCM 的负载:

{
    registeration_ids : [<id_1>, <id_2>],
    data : {
        title   : message_title,
        body    : message_body, 
        intended_user : message_user
    }
}

在 android 中即使应用程序在后台也会调用 FirebaseMessagingService.onMessageReceived() 但在 ios 中 didReceiveRemoteNotification() 仅在应用程序启动时调用,因此没有后台消息如果您发送数据消息,将会出现。

尝试将 content_available 设置为真。

From the fcm documentation :

Note: If you want to send messages consisting of only custom key-values to an iOS device when the app is in the background, set custom key-value pairs in the data key and set content_available to true.

{
    registeration_ids : [<id_1>, <id_2>],
    content_available: true,

    data : {
        title   : message_title,
        body    : message_body, 
        intended_user : message_user
    }
}

据我目前的了解,ios 方面无法正确解决此问题。它在 android 端完美运行,因为应用程序在所有状态(前景、背景和关闭)下都被唤醒。

您可以发送两种消息:

一个notification-message,由操作系统直接显示和处理。

由应用程序处理的 数据消息

如果您添加自定义标签,它现在会变成一条数据消息,必须由应用程序处理。您可以在数据消息中添加一个 content_available 标记以使应用程序知道该消息,但问题是如果应用程序处于前台,则数据消息仅在 ios 中传递给应用程序(打开)或在后台(最小化)。如果用户有 "force-closed" 应用程序(即使启用了后台通知),数据消息将不会传送到应用程序。

解决方案是在服务器端处理目标用户,并通过维护一对一的设备令牌与用户关系来解决多用户对一个设备令牌的问题。

我注意到如果通知优先级设置为高,当应用程序被强制关闭时通知会到达。

{  "notification": {
    "body" : "This week’s edition is now available.",
    "title": "Portugal vs. Denmark",
    "text": "5 to 1",
    "content_available": 1
  },
  "data" : {
    "volume" : "3.21.15",
    "contents" : "http://www.news-magazine.com/world-week/21659772"
  },
  "to" : "fqUk65A1kTE:APA91bG5...", // or set topic like "/topics/test"
  "priority" : "high"
}

对于 iOS 客户端应用程序,普通和高优先级类似于 APN 优先级 5 和 10。

根据 iOS 文档,默认优先级的通知可能未送达。

apns-priority: The priority of the notification. Specify one of the following values:

10–Send the push message immediately. Notifications with this priority must trigger an alert, sound, or badge on the target device. It is an error to use this priority for a push notification that contains only the content-available key.

5—Send the push message at a time that takes into account power considerations for the device. Notifications with this priority might be grouped and delivered in bursts. They are throttled, and in some cases are not delivered. If you omit this header, the APNs server sets the priority to 10.

更新 1:

以上通知是通过 FCM api 发送的,是在应用被终止时收到的。 在我点击设备上的通知后,这是应用程序启动后设备日志中显示的内容:

...didReceiveRemoteNotification: [gcm.message_id: 0:1468481012881485%e1d60a46e1d60a46, volume: 3.21.15, aps: {
        alert =     {
            body = "This week\U2019s edition is now available.";
            title = "Portugal vs. Denmark";
        };
    }, contents: http://www.news-magazine.com/world-week/21659772][;

注意数据部分也包含在收到的消息中。

更新二:

单个设备上的多个用户或多个设备上的一个用户。

在您的服务器端,您必须确保一个唯一的 fcm_id 只能分配给一个用户。这意味着一台设备分配给一位用户,因此每台设备只会通知一位用户。

此外,一个用户可以拥有多个 fcm_id,这意味着用户可以拥有更多设备并登录。

当 user_2 登录到 user_1 的同一设备时,fcm_id 必须与 user_1 分离并附加到 user_2。在这种方式下,只有当前登录的用户才会收到消息。

Firebase 的文档很差!

对于iOS,应用被终止时无法接收数据消息。但是他们的文档中没有任何地方提到这一点。所以我联系了 Firebase,他们是这样说的:

Though there is a content_available parameter, data messages cannot be received when the app is killed. It can only be received on background and in foreground. If you wish to receive data messages when the app is killed, you need to send it along a display messages.

因此,如果您曾经想过在 FCM 中对 android 和 Ios 使用相同的负载,那么最好为 ios 使用 APNS。

关键问题是向特定用户组发送最新登录身份的消息。

其实可以使用主题消息来解决问题。假设你有3个用户tags/groupsA​​,B,C。FCM在初始化的时候,注册到1个topic for All users,保证可以给所有的用户标签发消息。

对于特定的用户标签,如果用户以A登录,则订阅A。用户注销并以B登录后,检查用户是否订阅了A/C。如果是,取消订阅A/C,然后订阅B。这样可以避免处理数据部分涉及的标签。