【问题标题】:Send push to Android by C# using FCM (Firebase Cloud Messaging)使用 FCM(Firebase 云消息传递)通过 C# 向 Android 发送推送
【发布时间】:2016-09-21 15:08:39
【问题描述】:

我正在使用此代码通过 C# 和 GCM 发送通知消息,使用 Winforms、Webforms 等。现在我想发送到 FCM(Firebase 云消息传递)。我应该更新我的代码吗? :

public class AndroidGCMPushNotification
{
    public AndroidGCMPushNotification()
    {
        //
        // TODO: Add constructor logic here
        //
    }
    public string SendNotification(string deviceId, string message)
    {
        string SERVER_API_KEY = "server api key";        
        var SENDER_ID = "application number";
        var value = message;
        WebRequest tRequest;
        tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
        tRequest.Method = "post";
        tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";
        tRequest.Headers.Add(string.Format("Authorization: key={0}", SERVER_API_KEY));

        tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));

        string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + deviceId + "";
        Console.WriteLine(postData);
        Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        tRequest.ContentLength = byteArray.Length;

        Stream dataStream = tRequest.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();

        WebResponse tResponse = tRequest.GetResponse();

        dataStream = tResponse.GetResponseStream();

        StreamReader tReader = new StreamReader(dataStream);

        String sResponseFromServer = tReader.ReadToEnd();


        tReader.Close();
        dataStream.Close();
        tResponse.Close();
        return sResponseFromServer;
    }
}

但 GCM 已更改为 FCM。发送通知的代码是否相同? 我在哪里可以找到 SERVER_API_KEY?是一样的解决方案吗?

【问题讨论】:

  • 如果您对使用.Net Admin SDK的2019版本感兴趣,请查看我的回答here

标签: c# android firebase-cloud-messaging


【解决方案1】:

使用 c# 的 firebase 云消息传递: 适用于所有 .net 平台(asp.net、.netmvc、.netcore)

        WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
        tRequest.Method = "post";
        //serverKey - Key from Firebase cloud messaging server  
        tRequest.Headers.Add(string.Format("Authorization: key={0}", "AIXXXXXX...."));
        //Sender Id - From firebase project setting  
        tRequest.Headers.Add(string.Format("Sender: id={0}", "XXXXX.."));
        tRequest.ContentType = "application/json";
        var payload = new
        {
            to = "e8EHtMwqsZY:APA91bFUktufXdsDLdXXXXXX..........XXXXXXXXXXXXXX",
            priority = "high",
            content_available = true,
            notification = new
            {
                body = "Test",
                title = "Test",
                badge = 1
            },
            data = new 
            {
                key1 = "value1",
                key2 = "value2"
            }

        };

        string postbody = JsonConvert.SerializeObject(payload).ToString();
        Byte[] byteArray = Encoding.UTF8.GetBytes(postbody);
        tRequest.ContentLength = byteArray.Length;
        using (Stream dataStream = tRequest.GetRequestStream())
        {
            dataStream.Write(byteArray, 0, byteArray.Length);
            using (WebResponse tResponse = tRequest.GetResponse())
            {
                using (Stream dataStreamResponse = tResponse.GetResponseStream())
                {
                    if (dataStreamResponse != null) using (StreamReader tReader = new StreamReader(dataStreamResponse))
                        {
                            String sResponseFromServer = tReader.ReadToEnd();
                            //result.Response = sResponseFromServer;
                        }
                }
            }
        }

【讨论】:

  • 从哪里获取 SenderID?
  • @asmgx 您可以在 Firebase 控制台 > 项目设置 > 云消息选项卡中查看它。
  • 没关系。我找到了解决方案。 to : "/topics/all" 将向所有设备发送通知,或者如果您只想定位 IOS,请将 all 替换为 ios,对于 android,请替换为 `android'。这些是默认主题集。我猜。
  • 当我尝试运行此代码时,它给了我以下错误 - “远程服务器返回错误:(401)未经授权。”
  • 如果我想在结构中发送我的数据,那么我需要做什么?
【解决方案2】:

我正在使用这种方法并且效果很好:

 public class PushNotification
 {
     private static readonly ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        // firebase
     private static Uri FireBasePushNotificationsURL = new Uri("https://fcm.googleapis.com/fcm/send");
     private static string ServerKey = ConfigurationManager.AppSettings["FIREBASESERVERKEY"];

     public static async Task<bool> SendPushNotification(List<SendNotificationModel> notificationData)
     {
         try
         {
             bool sent = false;         
             foreach (var data in notificationData)
             {
                 var messageInformation = new Message()
                 {
                     notification = new Notification()
                     {
                         title = data.Title,
                         text = data.Message,
                         ClickAction = "FCM_PLUGIN_ACTIVITY"
                      },
                      data = data.data,
                      priority="high",
                      to =data.DeviceId
                 };
                 string jsonMessage = JsonConvert.SerializeObject(messageInformation);

                 //Create request to Firebase API
                 var request = new HttpRequestMessage(HttpMethod.Post, FireBasePushNotificationsURL);

                 request.Headers.TryAddWithoutValidation("Authorization", "key=" + ServerKey);
                 request.Content = new StringContent(jsonMessage, Encoding.UTF8, "application/json");

                 HttpResponseMessage result;
                 using (var client = new HttpClient())
                 {
                     result = await client.SendAsync(request);
                     sent =  result.IsSuccessStatusCode;
                 }             
             }

                return sent;
         }
         catch(Exception ex)
         {
             Logger.Error(ex);
             return false;
          }
    }
 }

【讨论】:

    【解决方案3】:

    我编写了这段代码,它对我有用。

    public static string ExcutePushNotification(string title, string msg, string fcmToken, object data) 
    {
    
            var serverKey = "AAAA*******************";
            var senderId = "3333333333333";
    
    
            var result = "-1";
    
            var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://fcm.googleapis.com/fcm/send");
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.Headers.Add(string.Format("Authorization: key={0}", serverKey));
            httpWebRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
            httpWebRequest.Method = "POST";
    
    
            var payload = new
            {
                notification = new
                {
                    title = title,
                    body = msg,
                    sound = "default"
                },
    
                data = new
                {
                    info = data
                },
                to = fcmToken,
                priority = "high",
                content_available = true,
    
            };
    
    
            var serializer = new JavaScriptSerializer();
    
            using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
            {
                string json = serializer.Serialize(payload);
                streamWriter.Write(json);
                streamWriter.Flush();
            }
    
            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            {
                result = streamReader.ReadToEnd();
            }
            return result;
    }
    

    【讨论】:

      【解决方案4】:

      您可以使用这个库,使用 Firebase 服务从 C# 后端下载here无缝发送推送通知@

      【讨论】:

      • 能否请您告诉我如何在不知道 ID 的情况下为所有注册设备发送通知。非常感谢。
      • 嗨 Nelson, to 值可以是设备的注册令牌、设备组的通知键或单个主题(以 /topics/ 为前缀)。要发送到多个主题,请使用条件参数。检查这些参考资料。 firebase.google.com/docs/cloud-messaging/http-server-reffirebase.google.com/docs/cloud-messaging/android/…
      • 嗨弗兰克,谢谢你的回答,我发现了另一种使用 appcenter、firebase 和 xamarin 做到这一点的方法,这是最好的和最简单的方法,它就像一个魅力。现在我正在接收和发送所有注册设备的推送通知。
      • 分享这个愚蠢的新闻 :-)
      【解决方案5】:
       public  SendNotice(int deviceType, string deviceToken, string message, int badge, int status, string sound)
          {
              AndroidFCMPushNotificationStatus result = new AndroidFCMPushNotificationStatus();
              try
              {
                  result.Successful = false;
                  result.Error = null;
                  var value = message;
                  WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
                  tRequest.Method = "post";
                  tRequest.ContentType = "application/json";
                  var serializer = new JavaScriptSerializer();
                  var json = "";
                  tRequest.Headers.Add(string.Format("Authorization: key={0}", "AA******"));
                  tRequest.Headers.Add(string.Format("Sender: id={0}", "11********"));
                 if (DeviceType == 2)
                  {
                      var body = new
                        {
                            to = deviceToken,
                            data = new
                            {
                                custom_notification = new
                                  {
                                      title = "Notification",
                                      body = message,
                                      sound = "default",
                                      priority = "high",
                                      show_in_foreground = true,
                                      targetScreen = notificationType,//"detail",
                                                                      },
                            },
      
                            priority = 10
                        };
      
                      json = serializer.Serialize(body);
                  }
                  else
                  {
                      var body = new
                      {
                          to = deviceToken,
                          content_available = true,
                          notification = new
                          {
                              title = "Notification",
                              body = message,
                              sound = "default",
                              show_in_foreground = true,
                          },
                          data = new
                          {
                              targetScreen = notificationType,
                              id = 0,
                          },
                          priority = 10
                      };
                      json = serializer.Serialize(body);
                  }
      
                  Byte[] byteArray = Encoding.UTF8.GetBytes(json);
      
                  tRequest.ContentLength = byteArray.Length;
      
                  using (Stream dataStream = tRequest.GetRequestStream())
                  {
                      dataStream.Write(byteArray, 0, byteArray.Length);
      
                      using (WebResponse tResponse = tRequest.GetResponse())
                      {
                          using (Stream dataStreamResponse = tResponse.GetResponseStream())
                          {
                              using (StreamReader tReader = new StreamReader(dataStreamResponse))
                              {
                                  String sResponseFromServer = tReader.ReadToEnd();
                                  result.Response = sResponseFromServer;
                              }
                          }
                      }
                  }
              }
              catch (Exception ex)
              {
                  result.Successful = false;
                  result.Response = null;
                  result.Error = ex;
              }
      }
      

      【讨论】:

      • "DeviceType" 表示 IOS 或 Android,Magic number 2 表示 IOS 设备
      【解决方案6】:

      这是在 ASP.Net REST API 中编写通知服务的另一种方法。

      public async Task<bool> NotifyAsync(string to, string title, string body)
      {
          try
          {
              // Get the server key from FCM console
              var serverKey = string.Format("key={0}", "Your server key - use app config");
      
              // Get the sender id from FCM console
              var senderId = string.Format("id={0}", "Your sender id - use app config");
      
              var data = new
              {
                  to, // Recipient device token
                  notification = new { title, body }
              };
      
              // Using Newtonsoft.Json
              var jsonBody = JsonConvert.SerializeObject(data);
      
              using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, "https://fcm.googleapis.com/fcm/send"))
              {
                  httpRequest.Headers.TryAddWithoutValidation("Authorization", serverKey);
                  httpRequest.Headers.TryAddWithoutValidation("Sender", senderId);
                  httpRequest.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
      
                  using (var httpClient = new HttpClient())
                  {
                      var result = await httpClient.SendAsync(httpRequest);
      
                      if (result.IsSuccessStatusCode)
                      {
                          return true;
                      }
                      else
                      {
                          // Use result.StatusCode to handle failure
                          // Your custom error handler here
                          _logger.LogError($"Error sending notification. Status Code: {result.StatusCode}");
                      }
                  }
              }
          }
          catch (Exception ex)
          {
              _logger.LogError($"Exception thrown in Notify Service: {ex}");
          }
      
          return false;
      }
      

      参考资料:

      using Microsoft.Extensions.Configuration;
      using Microsoft.Extensions.Logging;
      using Newtonsoft.Json;
      using System.Net.Http;
      using System.Text;
      using System.Threading.Tasks;
      

      【讨论】:

      • 好答案,只是一个问题是没有必要使用一次性HttpClient,而是使用它的单例实例。
      • @VedranMandić 同意。上面的例子如果足够好,可以快速参考。在即将发布的 ASP.net Core 2.1 (blogs.msdn.microsoft.com/webdev/2018/02/02/…) 中检查 HttpClientFactory。
      • @Santosh 如果您想向所有设备广播消息?你应该给“to”变量写什么?我们可以发送空或逗号分隔等.. 吗?谢谢
      • @ShortlyFD 发送到多个设备有点不同。 Google FCM 支持向设备组或主题发送消息。检查firebase.google.com/docs/cloud-messaging/android/send-multiple
      【解决方案7】:

      是的,您应该更新代码以使用 Firebase 消息接口。 here 有一个 GitHub 项目。

      using Stimulsoft.Base.Json;
      using System;
      using System.Collections.Generic;
      using System.IO;
      using System.Linq;
      using System.Net;
      using System.Text;
      using System.Web;
      
      namespace _WEBAPP
      {
          public class FireBasePush
          {
              private string FireBase_URL = "https://fcm.googleapis.com/fcm/send";
              private string key_server;
              public FireBasePush(String Key_Server)
              {
                  this.key_server = Key_Server;
              }
              public dynamic SendPush(PushMessage message)
              {
                  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(FireBase_URL);
                  request.Method = "POST";
                  request.Headers.Add("Authorization", "key=" + this.key_server);
                  request.ContentType = "application/json";
                  string json = JsonConvert.SerializeObject(message);
                  //json = json.Replace("content_available", "content-available");
                  byte[] byteArray = Encoding.UTF8.GetBytes(json);
                  request.ContentLength = byteArray.Length;
                  Stream dataStream = request.GetRequestStream();
                  dataStream.Write(byteArray, 0, byteArray.Length);
                  dataStream.Close();
                  HttpWebResponse respuesta = (HttpWebResponse)request.GetResponse();
                  if (respuesta.StatusCode == HttpStatusCode.Accepted || respuesta.StatusCode == HttpStatusCode.OK || respuesta.StatusCode == HttpStatusCode.Created)
                  {
                      StreamReader read = new StreamReader(respuesta.GetResponseStream());
                      String result = read.ReadToEnd();
                      read.Close();
                      respuesta.Close();
                      dynamic stuff = JsonConvert.DeserializeObject(result);
      
                      return stuff;
                  }
                  else
                  {
                      throw new Exception("Ocurrio un error al obtener la respuesta del servidor: " + respuesta.StatusCode);
                  }
              }
      
      
          }
          public class PushMessage
          {
              private string _to;
              private PushMessageData _notification;
      
              private dynamic _data;
              private dynamic _click_action;
              public dynamic data
              {
                  get { return _data; }
                  set { _data = value; }
              }
      
              public string to
              {
                  get { return _to; }
                  set { _to = value; }
              }
              public PushMessageData notification
              {
                  get { return _notification; }
                  set { _notification = value; }
              }
      
              public dynamic click_action
              {
                  get
                  {
                      return _click_action;
                  }
      
                  set
                  {
                      _click_action = value;
                  }
              }
          }
      
          public class PushMessageData
          {
              private string _title;
              private string _text;
              private string _sound = "default";
              //private dynamic _content_available;
              private string _click_action;
              public string sound
              {
                  get { return _sound; }
                  set { _sound = value; }
              }
      
              public string title
              {
                  get { return _title; }
                  set { _title = value; }
              }
              public string text
              {
                  get { return _text; }
                  set { _text = value; }
              }
      
              public string click_action
              {
                  get
                  {
                      return _click_action;
                  }
      
                  set
                  {
                      _click_action = value;
                  }
              }
          }
      }
      

      【讨论】:

        【解决方案8】:

        我已经发布了这个答案,因为这个问题被查看最多,并且这个服务器端代码是在 VS 2015 中用 C# 编写的,用于发送基于设备 ID 的单个设备或订阅主题到 Xamarin Android 应用程序的推送通知

        public class FCMPushNotification
        {
            public FCMPushNotification()
            {
                // TODO: Add constructor logic here
            }
        
            public bool Successful
            {
                get;
                set;
            }
        
            public string Response
            {
                get;
                set;
            }
            public Exception Error
            {
                get;
                set;
            }
        
        
        
            public FCMPushNotification SendNotification(string _title, string _message, string _topic)
            {
                FCMPushNotification result = new FCMPushNotification();
                try
                {
                    result.Successful = true;
                    result.Error = null;
                   // var value = message;
                    var requestUri = "https://fcm.googleapis.com/fcm/send";
        
                    WebRequest webRequest = WebRequest.Create(requestUri);
                    webRequest.Method = "POST";
                    webRequest.Headers.Add(string.Format("Authorization: key={0}", YOUR_FCM_SERVER_API_KEY));
                    webRequest.Headers.Add(string.Format("Sender: id={0}", YOUR_FCM_SENDER_ID));
                    webRequest.ContentType = "application/json";
        
                    var data = new
                    {
                       // to = YOUR_FCM_DEVICE_ID, // Uncoment this if you want to test for single device
                       to="/topics/"+_topic, // this is for topic 
                        notification=new
                        {
                            title=_title,
                            body=_message,
                            //icon="myicon"
                        }
                    };
                    var serializer = new JavaScriptSerializer();
                    var json = serializer.Serialize(data);
        
                    Byte[] byteArray = Encoding.UTF8.GetBytes(json);
        
                    webRequest.ContentLength = byteArray.Length;
                    using (Stream dataStream = webRequest.GetRequestStream())
                    {
                        dataStream.Write(byteArray, 0, byteArray.Length);
        
                        using (WebResponse webResponse = webRequest.GetResponse())
                        {
                            using (Stream dataStreamResponse = webResponse.GetResponseStream())
                            {
                                using (StreamReader tReader = new StreamReader(dataStreamResponse))
                                {
                                    String sResponseFromServer = tReader.ReadToEnd();
                                    result.Response = sResponseFromServer;
                                }
                            }
                        }
                    }
        
                }
                catch(Exception ex)
                {
                    result.Successful = false;
                    result.Response = null;
                    result.Error = ex;
                }
                return result;
            }
        }
        

        及其用途

        // start sending push notification to apps
                        FCMPushNotification fcmPush = new FCMPushNotification();                    
                        fcmPush.SendNotification("your notificatin title", "Your body message","news");
                        // end push notification
        

        【讨论】:

        • 如果我想将它发送到所有安装了应用程序的设备怎么办?
        • 谢谢。也可以发送直接推送:'to=_UserKey',而不是使用主题。
        【解决方案9】:

        这是来自 C# / Asp.net 的服务器端 Firebase 云请求的代码。
        请注意,您的客户端应该有相同的主题。
        例如

        FirebaseMessaging.getInstance().subscribeToTopic("news");
        
        public String SendNotificationFromFirebaseCloud()
        {
            var result = "-1";
            var webAddr = "https://fcm.googleapis.com/fcm/send";
        
            var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.Headers.Add("Authorization:key=" + YOUR_FIREBASE_SERVER_KEY);
            httpWebRequest.Method = "POST";
        
            using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
            {
                string json = "{\"to\": \"/topics/news\",\"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\",}}";
        
        
                streamWriter.Write(json);
                streamWriter.Flush();
            }
        
            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            {
                result = streamReader.ReadToEnd();
            }
        
            return result;
        }
        

        【讨论】:

        • 这非常适合使用主题消息发送到多个设备。谢谢。
        【解决方案10】:

        尝试发送一个 json 对象。 替换这个:

        tRequest.ContentType = " application/x-www-form-urlencoded;charset=UTF-8";    
        string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + deviceId + "";
                Console.WriteLine(postData);
                Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        

        为此:

        tRequest.ContentType = "application/json"; 
            var data = new
                {
                    to = deviceId,
                    notification = new
                    {
                        body = "This is the message",
                        title = "This is the title",
                        icon = "myicon"
                    }
                };
        
                var serializer = new JavaScriptSerializer();
                var json = serializer.Serialize(data);
        
                Byte[] byteArray = Encoding.UTF8.GetBytes(json);
        

        【讨论】:

          【解决方案11】:

          基于Teste的代码..我可以确认以下工作。我不能说这是否是“好”代码,但它确实有效,如果您最终遇到 GCM 到 FCM 服务器问题,它可以让您快速恢复并运行!

          public AndroidFCMPushNotificationStatus SendNotification(string serverApiKey, string senderId, string deviceId, string message)
          {
              AndroidFCMPushNotificationStatus result = new AndroidFCMPushNotificationStatus();
          
              try
              {
                  result.Successful = false;
                  result.Error = null;
          
                  var value = message;
                  WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
                  tRequest.Method = "post";
                  tRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
                  tRequest.Headers.Add(string.Format("Authorization: key={0}", serverApiKey));
                  tRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
          
                  string postData = "collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.message=" + value + "&data.time=" + System.DateTime.Now.ToString() + "&registration_id=" + deviceId + "";
          
                  Byte[] byteArray = Encoding.UTF8.GetBytes(postData);
                  tRequest.ContentLength = byteArray.Length;
          
                  using (Stream dataStream = tRequest.GetRequestStream())
                  {
                      dataStream.Write(byteArray, 0, byteArray.Length);
          
                      using (WebResponse tResponse = tRequest.GetResponse())
                      {
                          using (Stream dataStreamResponse = tResponse.GetResponseStream())
                          {
                              using (StreamReader tReader = new StreamReader(dataStreamResponse))
                              {
                                  String sResponseFromServer = tReader.ReadToEnd();
                                  result.Response = sResponseFromServer;
                              }
                          }
                      }
                  }
              }
              catch (Exception ex)
              {
                  result.Successful = false;
                  result.Response = null;
                  result.Error = ex;
              }
          
              return result;
          }
          
          
          public class AndroidFCMPushNotificationStatus
          {
              public bool Successful
              {
                  get;
                  set;
              }
          
              public string Response
              {
                  get;
                  set;
              }
              public Exception Error
              {
                  get;
                  set;
              }
          }
          

          【讨论】:

            【解决方案12】:
            猜你喜欢
            • 1970-01-01
            • 2017-03-10
            • 1970-01-01
            • 2021-11-02
            • 1970-01-01
            • 1970-01-01
            • 2022-08-16
            • 1970-01-01
            相关资源
            最近更新 更多