如何通过 CURL 向所有设备发送 Firebase 通知?

Posted

技术标签:

【中文标题】如何通过 CURL 向所有设备发送 Firebase 通知?【英文标题】:How do you send a Firebase Notification to all devices via CURL? 【发布时间】:2016-11-09 07:19:19 【问题描述】:

我正在尝试向所有应用用户(在 android 上)发送通知,基本上复制了通过 Firebase 管理控制台发送通知时发生的情况。这是我开始的 CURL 命令:

curl --insecure --header "授权:key=AIzaSyBidmyauthkeyisfineL-6NcJxj-1JUvEM" --header "Content-Type:application/json" -d "\"notification\":\"title\": \"note-Title\",\"body\":\"note-Body\"" https://fcm.googleapis.com/fcm/send

以下是解析出来的 JSON,以便您更容易看到:


"notification":
    "title":"note-Title",
    "body":"note-Body"
    

返回的响应只有两个字符:

就是这样,“到”这个词。 (标题报告 400)我怀疑这与我的 JSON 中没有“to”有关。一个“到”甚至会放什么?我没有定义任何主题,设备也没有注册任何东西。然而,他们仍然能够接收来自 Firebase 管理面板的通知。

由于 Firebase 通知处理的惊人限制,我想尝试“仅数据”JSON 包,如果您的应用在前台,通知将由您的处理程序处理,但如果您的应用在后台,它由 Firebase 服务在内部进行处理,并且永远不会传递给您的通知处理程序。显然,如果您通过 API 提交通知请求,则可以解决此问题,但前提是您仅使用数据执行此操作。 (这会破坏使用相同消息处理 ios 和 Android 的能力。)在我的任何 JSON 中用“数据”替换“通知”都没有效果。

好的,然后我在这里尝试了解决方案:Firebase Java Server to send push notification to all devices 在我看来,这似乎是在说“好的,尽管可以通过管理控制台向所有人发出通知……但实际上无法通过 API。”解决方法是让每个客户端订阅一个主题,然后将通知推送到该主题。所以首先是 onCreate 中的代码:

FirebaseMessaging.getInstance().subscribeToTopic("allDevices");

然后是我发送的新 JSON:


"notification":
    "title":"note-Title",
    "body":"note-Body"
    ,
"to":"allDevices"

所以现在我至少从服务器得到了真正的响应。 JSON 响应:


"multicast_id":463numbersnumbers42000,
"success":0,
"failure":1,
"canonical_ids":0,
"results":
    [
    
    "error":"InvalidRegistration"
    
    ]

它带有一个 HTTP 代码 200。好的...根据https://firebase.google.com/docs/cloud-messaging/http-server-ref 一个带有“InvalidRegistration”的 200 代码意味着注册令牌有问题。可能是?因为那部分文档是针对消息服务器的。通知服务器是否相同?不清楚。我在其他地方看到该主题可能需要几个小时才能激活。似乎这对于创建新的聊天室来说毫无用处,所以这似乎也不行。

当我能够从头开始编写一个应用程序并在几个小时内收到通知时,我感到非常兴奋,而我以前从未使用过 Firebase。在达到 Stripe.com 文档的水平之前,它似乎还有很长的路要走。

底线:有谁知道提供什么 JSON 来向所有运行该应用的设备发送消息以反映管理控制台功能?

【问题讨论】:

检查您使用的 api 令牌是否正确。还尝试将 GCM 消息发送到单个设备,看看是否有效。您可以通过在调试中启动应用程序并在 FirebaseInstanceIdService 上放置断点来获取 InstanceId 我没有看到“api token”出现在对 firebase.google.com/docs 的快速谷歌搜索中。您的意思是“ID 令牌”吗?还是“身份验证令牌”?还是您在谈论标题中提供的我的授权密钥?那个 很好:如果我将其更改为原来的样子,服务器响应将切换为“未经授权”,而不是我当前收到的错误消息。 该博客似乎是关于向特定设备发送消息,而不是像最初的讨论那样仅将消息发送给应用程序的所有用户。 阅读这篇博文了解更多详情 -> developine.com/… 【参考方案1】:

Firebase 通知没有用于发送消息的 API。幸运的是,它建立在 Firebase Cloud Messaging 之上,而 Firebase Cloud Messaging 正是拥有这样的 API。

借助 Firebase 通知和云消息传递,您可以通过三种方式向设备发送所谓的下游消息:

    to specific devices,如果你知道他们的设备 ID to groups of devices,如果你知道群组的注册ID to topics,这只是设备可以订阅的键

您会注意到,无法显式发送到所有设备。不过,您可以使用其中的每一个来构建此类功能,例如:通过在应用启动时订阅主题(例如/topics/all)或保留所有设备 ID 的列表,然后将消息发送给所有这些。

要发送到主题,您的命令中有语法错误。主题以/topics/ 开头。由于您的代码中没有它,因此服务器将 allDevices 解释为设备 ID。由于它是设备注册令牌的无效格式,因此会引发错误。

来自关于向主题发送消息的文档:

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA


  "to": "/topics/foo-bar",
  "data": 
    "message": "This is a Firebase Cloud Messaging Topic Message!",
   

【讨论】:

我尝试提交 "to":"/topic/allDevices","data":"message":"This is a Firebase Cloud Messaging Topic Message!" 并收到相同的 InvalidRegistration回复。我认为这意味着该主题无效。我在控制台中看不到主题数据库。 /topics/ 是复数 傻笑哦,错字,程序员的祸根。 ;) 新的回应是:"message_id":5115052numbers95180 这看起来肯定要成功得多。所以,听起来底线是,虽然管理控制台有一个强大的功能来通过“通知”传递通知,但没有办法从 API 提交中触发它,应该只是将自己转换为使用消息。 (丢失内置于通知中的调度和转换跟踪)我将寻找消息代码来处理接收。谢谢弗兰克。 :) 嗯...不是真的。通知控制台仅发送通知消息(请参阅this the documentation about message types)。它唯一能做的就是我们don't have an API for yet is sending to audiences。 iOS 也一样吗?我尝试了同样的方法,当应用程序处于活动状态时我会收到通知,但在后台它不起作用【参考方案2】:

我想出的向所有设备发送推送通知的最简单方法是为它们订阅“全部”主题,然后向该主题发送通知。 将此复制到您的主要活动中

FirebaseMessaging.getInstance().subscribeToTopic("all");

现在发送请求为


   "to":"/topics/all",
   "data":
   
      "title":"Your title",
      "message":"Your message"
      "image-url":"your_image_url"
   

这可能是低效或非标准的方式,但正如我上面提到的,它是最简单的。如果您有更好的方式向所有设备发送推送通知,请发布。

如果您不熟悉使用 Firebase Cloud Messaging Tutorial - Push Notifications using FCM

发送推送通知,可以按照本教程进行操作

要向主题的组合 发送消息,请指定一个条件,这是一个指定目标主题的布尔表达式。例如,以下条件将向订阅了TopicATopicBTopicC 的设备发送消息:


   "data":
   
      "title": "Your title",
      "message": "Your message"
      "image-url": "your_image_url"
   ,
   "condition": "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"

在FCM documentation上阅读更多关于条件和主题的信息

【讨论】:

这对我来说很有意义。但是和你一样,我不确定它是否效率低下。请问,有人可以澄清一下吗? 我不认为它效率低下,这可能是向所有设备发送推送通知的唯一可能方式(至少我找不到任何其他方式) 最佳答案! :) 很好的答案。由于没有在任何地方提及它,重要的是要知道您将在 Service 中收到此类消息,该消息在 #onMessageReceived 函数中扩展 FirebaseMessagingService。因此通知不会自动显示,您必须自己处理。【参考方案3】:

编辑:似乎不再支持此方法(感谢@FernandoZamperin)。请看看其他答案!

您可以使用condition 键向不在组中的实例发送消息,而不是订阅主题。您的数据可能如下所示:


    "data": 
        "foo": "bar"
    ,
    "condition": "!('anytopicyoudontwanttouse' in topics)"

见https://firebase.google.com/docs/cloud-messaging/send-message#send_messages_to_topics_2

【讨论】:

这是最好的答案。它可以立即运行,无需应用程序更新。太棒了! 终于找到了——他们真的应该让它更明显地使用它 这看起来很有希望,但它真的有效吗?它看起来像一个黑客。我在一个示例项目上进行了尝试,它可以工作。但是,我不确定它是否适用于拥有数千名活跃用户的产品应用程序。有人用 prod 应用试过吗? 我使用这种方法已经有一段时间了,并且运行良好,今天由于某种原因,我将通知发送到旧版 api,它返回 message_id 没有错误,但设备没有收到推送通知,任何猜测会是什么问题?测试发送到单个令牌,它工作正常。 @VitVeres 我向 Firebase 支持团队发送了一个问题,他们回复我为:“不支持您当前使用表达式来扇出推送通知。请确保表达式中列出的主题存在于你的应用程序项目。”,所以我想我必须在我的应用程序中实现主题。【参考方案4】:

一种方法是让所有用户的设备都订阅一个主题。这样,当您将消息定位到特定主题时,所有设备都会收到它。我认为 Firebase 控制台中的通知部分就是这样做的。

【讨论】:

阅读这篇博文了解更多详情 -> developine.com/…【参考方案5】:

我正在为我的 Ionic Cordova 应用推送通知寻找解决方案。

感谢 Syed Rafay 的回答。

app.component.ts

const options: PushOptions = 
  android: 
    topics: ['all']
  ,

服务器文件

"to" => "/topics/all",

【讨论】:

【参考方案6】:

只需让所有登录的用户订阅特定主题,然后向该主题发送通知。

【讨论】:

【参考方案7】:

在 Firebase 控制台上查看您的主题列表。

    转到 Firebase 控制台

    点击侧边菜单中的成长

    点击云消息

    点击发送您的第一条消息

    在通知部分,输入通知标题通知文本

    点击下一步

    在目标部分点击主题

    点击Message topic文本框,然后你可以看到你的主题(我没有创建主题叫android或ios,但我可以看到这两个主题。

    当您发送推送通知时,将此添加为您的条件。

    "condition"=> "'all' in topic || 'android' in topic || 'ios' in topic",

全身

array(
    "notification"=>array(
        "title"=>"Test",
        "body"=>"Test Body",
    ),
    "condition"=> "'all' in topics || 'android' in topics || 'ios' in topics",
);

如果您有更多主题,您可以添加具有||(或)条件的主题,然后所有用户都会收到您的通知。经过测试并为我工作。

【讨论】:

【参考方案8】:

对于想知道如何在 cordova 混合应用程序中做到这一点的任何人:

在 onDeviceReady() 函数内的 index.js -> 写入:

  subscribe();

(写在函数的顶部很重要!)

然后,在同一个文件 (index.js) 中找到:

函数订阅()

 FirebasePlugin.subscribe("write_here_your_topic", function()

 ,function(error)

     logError("Failed to subscribe to topic", error);
 );
 

在这里写下你自己的话题->"write_here_your_topic"

【讨论】:

【参考方案9】:

这是一个 php Admin-SDK 示例,用于为用户订阅主题并通过设备令牌或主题向设备发送消息。请注意,订阅用户时会自动创建主题。

$testTokens = ['device token 1', 'device token 2', ....]

// CREDENTIALS, YOU HAVE TO DOWNLOAD IT FROM FIREBASE CONSOLE.
$factory = (new Factory())->withServiceAccount('credentials.json');

$messaging = $factory->createMessaging();

// Subscribe a token or a group of tokens to a topic (this topic is created automatically if not exists)
// YOU CAN DO THIS IN THE MOBILE APP BUT IS BETTER DO IT IN THE API.
$result = $messaging->subscribeToTopic('all', $testTokens); // 'all' is the topic name

// Send a message to a specific Topic (Channel) 
$message = CloudMessage::withTarget('topic', 'all')
    ->withNotification(Notification::create('Global message Title', 'Global message Body'))
    ->withData(['key' => 'value']); // optional
$messaging->send($message);

// Send a message to a token or a grup of tokens (ONLY!!!)
 foreach($testTokens as $i=>$token)
     $message = CloudMessage::withTarget('token', $token)
         ->withNotification(Notification::create('This is the message Title', 'This is the message Body'))
         ->withData(['custom_index' => $i]); // optional
     $messaging->send($message);

您可以查看此回购以获取更多详细信息:firebase-php-admin-sdk

【讨论】:

【参考方案10】:

您可以使用“/topics/all”向所有设备发送通知

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA


  "to": "/topics/all",
  "notification": "title":"Notification title", "body":"Notification body", "sound":"default", "click_action":"FCM_PLUGIN_ACTIVITY", "icon":"fcm_push_icon" ,
  "data": 
    "message": "This is a Firebase Cloud Messaging Topic Message!",
   

【讨论】:

这是新功能吗?或者这是否需要应用订阅“全部”? 这是默认功能。我不订阅任何主题。它对我有用。但我做了令牌注册。 “getToken” 您会收到一个消息 ID,是的,但是除非您确实有一个名为“all”的主题,否则不会向任何设备发送任何内容。 没有。我在我的 android 设备(两个)中收到了通知。你要我附上我的屏幕截图吗?我在 ioinc 之上构建我的应用程序。 这对我有用。不知道为什么这被否决了。

以上是关于如何通过 CURL 向所有设备发送 Firebase 通知?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# 向所有设备发送带有图像的 FCM 通知?

通过通知中心向所有用户发送推送通知

如何通过 PHP 发送带有 pem 证书的 curl 请求?

向 Parse 发送推送通知,如何在设备中接收它

markdown 向Telegram发送通知消息(通过cURL)

如何使用 Firebase Cloud Messaging 向所有设备发送通知