如何在C# .Net上通过GCM发送Android推送通知

9

我对所有Android GCM推送通知都是新手,我已经阅读了堆栈帖子,但没有得到明确的答案。 我也阅读了在Android中创建推送通知以更好地了解GCM的工作原理。 我还使用了SDK提供的gcm-demo-server和gcm-demo-client。 但是,这里是我的疑问和我迄今为止所尝试的内容:

  1. Regarding the link I have put, the phone which has the app registers to get the registration key. Is this a unique key for all phones which uses the same app?
  2. Does this registration key expires in any case? (E.g. App running on background)
  3. Assuming that I have the registration key, I have tried the following code snippet to push notification via GCM to my app. This is written on c# .net. Please let me know whether what I have mentioned above can be achieved using the following code snippet:

         private string SendGCMNotification(string apiKey, string postData, string postDataContentType = "application/json")
        {
            ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);
    
            // MESSAGE CONTENT
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
    
            // CREATE REQUEST
            HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
            Request.Method = "POST";
            Request.KeepAlive = false;
            Request.ContentType = postDataContentType;
            Request.Headers.Add(string.Format("Authorization: key={0}", apiKey));
            Request.ContentLength = byteArray.Length;
    
            Stream dataStream = Request.GetRequestStream();
            dataStream.Write(byteArray, 0, byteArray.Length);
            dataStream.Close();
    
            // SEND MESSAGE
            try
            {
                WebResponse Response = Request.GetResponse();
                HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode;
                if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden))
                {
                    var text = "Unauthorized - need new token";
                }
                else if (!ResponseCode.Equals(HttpStatusCode.OK))
                {
                    var text = "Response from web service isn't OK";
                }
    
                StreamReader Reader = new StreamReader(Response.GetResponseStream());
                string responseLine = Reader.ReadToEnd();
                Reader.Close();
    
                return responseLine;
            }
            catch (Exception e)
            {
            }
            return "error";
        }
    
  4. Is there a direct way of sending push notifications without the phone first being registered in our custom server?

6个回答

19

参考代码:

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;
    }
}

参考链接:

http://www.codeproject.com/Tips/434338/Android-GCM-Push-Notification


由于某些原因,上述代码无法正常工作。我已经假定设备ID是注册密钥。但是当我尝试使用http://helmibaraja.com/gcm_demo.html推送消息时,它可以正常工作。有什么想法吗? - Pavan Welihinda
1
通过将 "®istration_id=" 更改为 "&registration_id=",使其正常工作。谢谢大家 :) - Pavan Welihinda
2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Kelly Elton
这对我没有用。但Charitha的答案有效。 :D - Olivia

7
代码看起来有点长,但它可以正常工作。在实现以下C#项目代码两天后,我成功地向我的手机发送了推送通知。我参考了一篇关于这个实现的链接,但无法在此处发布。因此,我将与您分享我的代码。如果您想在线测试通知,可以访问此链接:link
注意:我已经在方法体中硬编码了apiKey、deviceId和postData,请在请求中传递apiKey、deviceId和postData,并从方法体中删除它们。如果您想传递消息字符串,请自行添加。
public string SendGCMNotification(string apiKey, string deviceId, string postData)
{
    string postDataContentType = "application/json";
    apiKey = "AIzaSyC13...PhtPvBj1Blihv_J4"; // hardcorded
    deviceId = "da5azdfZ0hc:APA91bGM...t8uH"; // hardcorded

    string message = "Your text";
    string tickerText = "example test GCM";
    string contentTitle = "content title GCM";
    postData =
    "{ \"registration_ids\": [ \"" + deviceId + "\" ], " +
      "\"data\": {\"tickerText\":\"" + tickerText + "\", " +
                 "\"contentTitle\":\"" + contentTitle + "\", " +
                 "\"message\": \"" + message + "\"}}";


    ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);

    //
    //  MESSAGE CONTENT
    byte[] byteArray = Encoding.UTF8.GetBytes(postData);

    //
    //  CREATE REQUEST
    HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
    Request.Method = "POST";
    Request.KeepAlive = false;
    Request.ContentType = postDataContentType;
    Request.Headers.Add(string.Format("Authorization: key={0}", apiKey));
    Request.ContentLength = byteArray.Length;

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

    //
    //  SEND MESSAGE
    try
    {
        WebResponse Response = Request.GetResponse();
        HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode;
        if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden))
        {
            var text = "Unauthorized - need new token";
        }
        else if (!ResponseCode.Equals(HttpStatusCode.OK))
        {
            var text = "Response from web service isn't OK";
        }

        StreamReader Reader = new StreamReader(Response.GetResponseStream());
        string responseLine = Reader.ReadToEnd();
        Reader.Close();

        return responseLine;
    }
    catch (Exception e)
    {
    }
    return "error";
}

public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
    return true;
}

你可能不熟悉apiKey、deviceId这些词汇,别担心,我会解释它们是什么以及如何创建。

apiKey
定义和作用:发送请求到GCM服务器时使用的密钥。
创建方法:参考这篇文章

deviceId
定义和作用:也称为RegistrationId。这是一个唯一的标识设备的ID。当你想要向特定设备发送通知时,需要使用此ID。
创建方法:这取决于你如何实现应用程序。对于cordova,我使用了一个简单的pushNotification插件。你可以使用这个插件轻松地创建deviceId/RegistrationId。为此,你需要有一个senderId。谷歌搜索如何创建senderId,它非常简单=)

如果有人需要帮助,请留言。祝编码愉快。
-Charitha-


请查看以下链接:https://srimansaswat.wordpress.com/2016/11/15/how-to-send-push-notification-to-your-android-device-using-c-code/ - Sriman Saswat Suvankar

3

2

这个方法对我来说从未起作用,而且很难调试,同时传递注册令牌列表也不够清晰 - 希望传递字符串数组而不是逗号分隔的字符串 - 事实上,这只是一个非常简单的POST请求,我自己创建了一个类,其中包含一个返回服务器响应的方法,它运行得非常好:

用法

       //Registration Token 
        string[] registrationIds ={"diks4vp5......","erPjEb9....."};

        AndroidGcmPushNotification gcmPushNotification = new 
        AndroidGcmPushNotification(
            "API KEY", registrationIds, "Hello World"
            );
        gcmPushNotification.SendGcmNotification();

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Web.Script.Serialization;


public class AndroidGcmPushNotification
{
private readonly string _apiAccessKey;
private readonly string[] _registrationIds;
private readonly string _message;
private readonly string _title;
private readonly string _subtitle;
private readonly string _tickerText;
private readonly bool _vibrate;
private readonly bool _sound;

public AndroidGcmPushNotification(string apiAccessKey, string[] registrationIds, string message, string title = "",
    string subtitle = "", string tickerText = "", bool vibrate = true, bool sound = true )
{
    _apiAccessKey = apiAccessKey;
    _registrationIds = registrationIds;
    _message = message;
    _title = title;
    _subtitle = subtitle;
    _tickerText = tickerText;
    _vibrate = vibrate;
    _sound = sound;
}

public string SendGcmNotification()
{

    //MESSAGE DATA
    GcmPostData data = new GcmPostData()
    {
        message = _message,
        title = _title,
        subtitle = _subtitle,
        tickerText = _tickerText,
        vibrate = _vibrate,
        sound = _sound
    };

    //MESSAGE FIELDS 
    GcmPostFields fields = new GcmPostFields();
    fields.registration_ids = _registrationIds;
    fields.data = data;

    //SERIALIZE TO JSON 
    JavaScriptSerializer jsonEncode = new JavaScriptSerializer();

    //CONTENTS
    byte[] byteArray = Encoding.UTF8.GetBytes(jsonEncode.Serialize(fields));

    //REQUEST
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
    request.Method = "POST";
    request.KeepAlive = false;
    request.ContentType = "application/json";
    request.Headers.Add($"Authorization: key={_apiAccessKey}");
    request.ContentLength = byteArray.Length;

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


    //SEND REQUEST
    try
    {
        WebResponse response = request.GetResponse();
        {
            StreamReader reader = new StreamReader(response.GetResponseStream());
            string responseLine = reader.ReadToEnd();
            reader.Close();

            return responseLine;
        }
    }
    catch (Exception e)
    {
        return e.Message;
    }

}
private class GcmPostFields
{
    public string[] registration_ids { get; set; }
    public GcmPostData data { get; set; }

}
private class GcmPostData
{
    public string message { get; set; }
    public string title { get; set; }
    public string subtitle { get; set; }
    public string tickerText { get; set; }
    public bool vibrate { get; set; }
    public bool sound { get; set; }
}

}

1

这里有一个名为PushSharp的包,可以与几乎所有流行的通知API进行通信。

示例代码:

// Configuration
var config = new GcmConfiguration ("GCM-SENDER-ID", "AUTH-TOKEN", null);

// Create a new broker
var gcmBroker = new GcmServiceBroker (config);

// Wire up events
gcmBroker.OnNotificationFailed += (notification, aggregateEx) => {

    aggregateEx.Handle (ex => {

        // See what kind of exception it was to further diagnose
        if (ex is GcmNotificationException) {
            var notificationException = (GcmNotificationException)ex;

            // Deal with the failed notification
            var gcmNotification = notificationException.Notification;
            var description = notificationException.Description;

            Console.WriteLine ($"GCM Notification Failed: ID={gcmNotification.MessageId}, Desc={description}");
        } else if (ex is GcmMulticastResultException) {
            var multicastException = (GcmMulticastResultException)ex;

            foreach (var succeededNotification in multicastException.Succeeded) {
                Console.WriteLine ($"GCM Notification Failed: ID={succeededNotification.MessageId}");
            }

            foreach (var failedKvp in multicastException.Failed) {
                var n = failedKvp.Key;
                var e = failedKvp.Value;

                Console.WriteLine ($"GCM Notification Failed: ID={n.MessageId}, Desc={e.Description}");
            }

        } else if (ex is DeviceSubscriptionExpiredException) {
            var expiredException = (DeviceSubscriptionExpiredException)ex;

            var oldId = expiredException.OldSubscriptionId;
            var newId = expiredException.NewSubscriptionId;

            Console.WriteLine ($"Device RegistrationId Expired: {oldId}");

            if (!string.IsNullOrWhitespace (newId)) {
                // If this value isn't null, our subscription changed and we should update our database
                Console.WriteLine ($"Device RegistrationId Changed To: {newId}");
            }
        } else if (ex is RetryAfterException) {
            var retryException = (RetryAfterException)ex;
            // If you get rate limited, you should stop sending messages until after the RetryAfterUtc date
            Console.WriteLine ($"GCM Rate Limited, don't send more until after {retryException.RetryAfterUtc}");
        } else {
            Console.WriteLine ("GCM Notification Failed for some unknown reason");
        }

        // Mark it as handled
        return true;
    });
};

gcmBroker.OnNotificationSucceeded += (notification) => {
    Console.WriteLine ("GCM Notification Sent!");
};

// Start the broker
gcmBroker.Start ();

foreach (var regId in MY_REGISTRATION_IDS) {
    // Queue a notification to send
    gcmBroker.QueueNotification (new GcmNotification {
        RegistrationIds = new List<string> { 
            regId
        },
        Data = JObject.Parse ("{ \"somekey\" : \"somevalue\" }")
    });
}

// Stop the broker, wait for it to finish   
// This isn't done after every message, but after you're
// done with the broker
gcmBroker.Stop ();

0
我曾使用Firebase的FCM开发Android和IOS应用程序。这段代码可以正常工作。中间层是ASP.NET API。在Visual Studio中启动项目,选择API并创建一个控制器。将您的server_api_key和sender id添加到Web.config文件中。同时添加用户的FCM server_api_key和sender id。
<appSettings>
    <add key="SERVER_API_KEY" value=""/>
    <add key="SENDER_ID" value=""/>
</appSettings>

以下代码可用于添加您的控制器:
 using System;
    using System.Net;
    using System.Web.Http;
    using System.Web.Script.Serialization;
    using System.Configuration;
    using System.IO;

    namespace pushios.Controllers
        {

        public class HomeController : ApiController
            {
                [HttpGet]

        [Route("sendmessage")]

                public IHttpActionResult SendMessage()
              {
                    var data = new {
                        to = "Device Token",
                        data = new
                        {
                           //To be adding your json data
                            body="Test",
                            confId= "",
                            pageTitle= "test",
                            pageFormat= "",
                            dataValue= "",
                            title= "C#",
                            webviewURL= "",
                            priority = "high",
                            notificationBlastID = "0",
                            status = true
                        }
                    };
                    SendNotification(data);
                    return Ok();
                }
                public void SendNotification(object data)
                {
                    var Serializer = new JavaScriptSerializer();
                    var json = Serializer.Serialize(data);
                    Byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(json);

                    SendNotification(byteArray);
                }
                public void SendNotification(Byte[] byteArray)
                {

                    try
                    {
                        String server_api_key = ConfigurationManager.AppSettings["SERVER_API_KEY"];
                        String senderid = ConfigurationManager.AppSettings["SENDER_ID"];

                        WebRequest type = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
                        type.Method = "post";
                        type.ContentType = "application/json";
                        type.Headers.Add($"Authorization: key={server_api_key}");
                        type.Headers.Add($"Sender: id={senderid}");

                        type.ContentLength = byteArray.Length;
                        Stream datastream = type.GetRequestStream();
                        datastream.Write(byteArray, 0, byteArray.Length);
                        datastream.Close();

                        WebResponse respones = type.GetResponse();
                        datastream = respones.GetResponseStream();
                        StreamReader reader = new StreamReader(datastream);

                        String sresponessrever = reader.ReadToEnd();
                        reader.Close();
                        datastream.Close();
                        respones.Close();

                    }
                    catch (Exception)
                    {
                        throw;
                    }

                }
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接