44

有没有办法使用 google 的 firebase 发送静默 APNS?似乎如果应用程序在后台,它总是会向用户显示通知。

谢谢?

4

6 回答 6

51

您可以使用 FCM 服务器 API https://firebase.google.com/docs/cloud-messaging/http-server-ref发送静默 APNS 消息

特别是您需要使用:

  • 数据字段:

此参数指定消息负载的自定义键值对。

例如,使用数据:{"score":"3x1"}:

在 iOS 上,如果消息是通过 APNS 发送的,它代表自定义数据字段。如果通过 FCM 连接服务器发送,则在 AppDelegate application:didReceiveRemoteNotification: 中表示为键值字典。

密钥不应是保留字(“from”或任何以“google”或“gcm”开头的词)。请勿使用此表中定义的任何字词(例如 collapse_key)。

建议使用字符串类型的值。您必须将对象或其他非字符串数据类型(例如整数或布尔值)中的值转换为字符串

  • content_available字段:

在 iOS 上,使用此字段表示 APNS 有效负载中的可用内容。当发送通知或消息并将其设置为 true 时,将唤醒非活动客户端应用程序。在 Android 上,默认情况下,数据消息会唤醒应用程序。在 Chrome 上,目前不支持。

完整文档: https ://firebase.google.com/docs/cloud-messaging/http-server-ref#downstream-http-messages-json

于 2016-06-03T18:33:47.523 回答
48

对于使用 FCM 服务器的真正静默通知(前台和后台),请使用以下字段:

"to" : "[token]",
"content_available": true,
"priority": "high",
"data" : {
  "key1" : "abc",
  "key2" : 123
}

注意:确保您在 FCM 中使用“content_available”而不是“content-available”。它已为 APNS 转换,否则将无法正确接收。这种差异让我困惑了一段时间。

于 2017-04-03T14:27:42.413 回答
18

我在我的博客上更详细地解释了这个主题。 http://blog.boxstory.com/2017/01/how-to-send-silent-push-notification-in.html

** 关键点是:“content_available:true”

这是示例 JSON

{
    "to" : "<device>",
    "priority": "normal",
    "content_available": true, <-- this key is converted to 'content-available:1'
    "notification" : {
      "body" : "noti body",
      "title" : "noti title",
      "link": "noti link "
    }
}

注意:如果发送了上述示例 JSON,则通知将对用户可见。如果您不希望用户看到推送通知,请在下面使用。

{
  "to": "<device>",
  "priority": "normal",
  "content_available": true <-- this key is converted to 'content-available:1'
}
于 2017-01-08T09:25:13.833 回答
8

对于不使用Legacy HTTP其他答案中显示的 as 并使用 latest 的人v1 HTTP protocol,我终于找到了发送静默通知的正确方法。

NodeJS 示例使用firebase-admin

    const message = {
      apns: {
        payload: {
          aps: {
            "content-available": 1,
            alert: ""
          }
        }
      },
      token: "[token here - note that you can also replace the token field with `topic` or `condition` depending on your targeting]"
    };

    admin
      .messaging()
      .send(message)
      .then(response => {
        // Response is a message ID string.
        console.log("Successfully sent message:", response);
      })
      .catch(error => {
        console.log("Error sending message:", error);
      });

解释:

  • 似乎apnsFirebase 中的有效负载没有被转换,v1 HTTP protocol所以你需要原来"content-available": 1的。
  • alert: ""也是必要的。如果您曾经尝试使用类似的方式发送静默通知Pusher,您会发现只有content-available无法触发它。相反,添加其他字段,例如soundoralert可以使其工作。请参阅iOS 7 中的静默推送通知不起作用。由于 Firebase 禁止空声,我们可以为此使用空警报。
于 2019-05-16T09:47:48.093 回答
5

其他解决方案对我不起作用。我想要一个向 iOS 和 Android 发送数据消息的解决方案。

从我的测试中,我发现当我的 iOS 应用程序在后台时可靠地发送数据消息的唯一方法是包含一个空的通知有效负载。

此外,正如其他答案所提到的,您需要包含content_availableand priority

要使用 curl 命令对此进行测试,您需要FCM 服务器密钥和应用程序中的 FCM 令牌。

仅适用于 iOS 的示例 curl 命令。(可靠的数据消息,没有可见的通知)

curl -X POST \
  https://fcm.googleapis.com/fcm/send \
  -H 'authorization: key=server_key_here' \
  -H 'content-type: application/json' \
  -d '{
  "to": "fcm_token_here", 
  "priority": "high",
  "content_available": true,
  "notification": {
    "empty": "body"
  },
  "data": {
    "key1": "this_is_a_test",
    "key2": "abc",
    "key3": "123456",
  }
}'

用您自己的替换server_key_here及以上。fcm_token_here

AppDelegate当应用程序在后台并且不应显示 UI 消息时,应调用您的类中的以下方法。

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    //get data from userInfo

    completionHandler(UIBackgroundFetchResult.newData)
}

以下是使用云功能和打字稿发送到主题的方法。

const payload = {
    notification: {
        empty: "message"
    },
    data: {
        key1: "some_value",
        key2: "another_value",
        key3: "one_more"
    }
}

const options = {
    priority: "high",
    contentAvailable: true //wakes up iOS
}

return admin.messaging().sendToTopic("my_topic", payload, options)
    .then(response => {
        console.log(`Log some stuff`)
    })
    .catch(error => {
        console.log(error);
    });

以上似乎始终适用于 iOS,有时也适用于 Android。我得出的结论是,我的后端需要在发送推送通知之前确定平台才能最有效。

于 2020-08-15T20:55:00.537 回答
1

我需要向主题发送预定通知。上面没有什么对我有用,但我终于得到了应用程序委托的application(application:didReceiveRemoteNotification:fetchCompletionHandler:)一致调用。这是我最终在index.js云函数文件中所做的完整示例(请注意,您需要"apns-push-type": "background""apns-priority": "5"标题,以及对象"content-available": 1内的条目aps):

const admin = require("firebase-admin");
const functions = require("firebase-functions");

exports.sendBackgroundFetchNotification = functions.pubsub.schedule("every 1 hours").onRun((context) => {
  const message = {
    data: {},
    apns: {
      headers: {
        "apns-push-type": "background",
        "apns-priority": "5",
      },
      payload: {
        aps: {
          "content-available": 1,
          "alert": {},
        },
      },
    },
    topic: "[Topic_Name_Here]",
  };

  return admin
    .messaging()
    .send(message)
    .then(response => {
      // Response is a message ID string.
      console.log("Successfully sent message:", response);
      return null;
    })
    .catch(error => {
      console.log("Error sending message:", error);
      return null;
    });
});

如果您不想在部署后等待该功能触发,只需进入 Google 云控制台功能部分 ( https://console.cloud.google.com/functions/list ) 并单击该功能名称,然后单击“测试”,最后单击“测试功能”。

值得注意的是,此代码使用 FCM 较新的 HTTP v1 协议,它允许您根据 Apple 的规范构建消息对象(下面的有用链接)。

https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns https://developer.apple.com/文档/用户通知/setting_up_a_remote_notification_server/generating_a_remote_notification

于 2022-01-04T22:03:11.590 回答