GCM Push Notification with Asp.Net

2019-01-07 11:35发布

问题:

As you may have seen, Google is migrating its Push Notification System.

http://developer.android.com/guide/google/gcm/c2dm.html

Is there any sample or guide line available for implementing Google Cloud Messaging (GCM) by using an Asp.Net application?

回答1:

I have a piece of code which is working fine for me and could be helpful, I tested it out...

void send(string regId)
{
    var applicationID = "xxxxxxxx";


    var SENDER_ID = "xxxxx";
    var value = txtMsg.Text;
    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}", applicationID));

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

    // string postData = "{ 'registration_id': [ '" + regId + "' ], 'data': {'message': '" + txtMsg.Text + "'}}";
    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=" + regId + "";
    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();

    lblStat.Text = sResponseFromServer;
    tReader.Close();
    dataStream.Close();
    tResponse.Close();
}


回答2:

here is the code in c#

 WebRequest tRequest;
        tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
        tRequest.Method = "post";
        tRequest.ContentType = "application/x-www-form-urlencoded";
        tRequest.Headers.Add(string.Format("Authorization: key={0}", GoogleAppID));
String collaspeKey = Guid.NewGuid().ToString("n");
String postData=string.Format("registration_id={0}&data.payload={1}&collapse_key={2}", DeviceID, "Pickup Message" + DateTime.Now.ToString(), collaspeKey);
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();


回答3:

A while back I had been playing around with C2DM to send push notifications. I altered my code as per changes mentioned on this page: http://developer.android.com/guide/google/gcm/c2dm.html#server to make use for GCM service:

Private Sub btnPush_Click(sender As Object, e As System.EventArgs) Handles btnPush.Click
    lblResponse.Text = SendNotification(AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA)
End Sub

My SendNotification function:

Private Function SendNotification(ByVal authstring As String) As String
    ServicePointManager.ServerCertificateValidationCallback = Function(sender As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) True
    Dim request As WebRequest = WebRequest.Create("https://android.googleapis.com/gcm/send")
    request.Method = "POST"
    request.ContentType = "application/x-www-form-urlencoded"
    request.Headers.Add(String.Format("Authorization: key={0}", authstring))
    Dim collaspeKey As String = Guid.NewGuid().ToString("n")
    Dim postData As String = String.Format("registration_id={0}&data.payload={1}&collapse_key={2}", deviceList.SelectedValue, txtPayload.Text, collaspeKey)
    Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData)
    request.ContentLength = byteArray.Length
    Dim dataStream As Stream = request.GetRequestStream()
    dataStream.Write(byteArray, 0, byteArray.Length)
    dataStream.Close()
    Dim response As WebResponse = request.GetResponse()
    dataStream = response.GetResponseStream()
    Dim reader As New StreamReader(dataStream)
    Dim responseFromServer As String = reader.ReadToEnd()
    reader.Close()
    dataStream.Close()
    response.Close()

    Return responseFromServer
End Function

It seems that GCM does not require you to authenticate against Google to obtain an auth key (as the case was with C2DM). Instead, you'll require an API key which is being passed to the SendNotification function. This page should help you get your API key set up: http://developer.android.com/guide/google/gcm/gs.html

The code for my web form is below just in case:

<form id="form1" runat="server">
<div>
    <asp:DropDownList ID="deviceList" runat="server">
        <asp:ListItem Value="device-id-goes-here">Eclipse AVD</asp:ListItem>
        <asp:ListItem Value="device-id-goes-here">My Phone 1</asp:ListItem>
        <asp:ListItem Value="device-id-goes-here">My Phone 2</asp:ListItem>
    </asp:DropDownList>
    <br /><br />
    <asp:TextBox ID="txtPayload" runat="server" Width="480px"></asp:TextBox>
    <br /><br />
    <asp:Button ID="btnPush" runat="server" Text="Push" />
    <asp:Label ID="lblResponse" runat="server" Text=""></asp:Label>
</div>
</form>

As for creating your Android app to receiving the push notifications, check out this link: http://developer.android.com/guide/google/gcm/gs.html#android-app

Don't forget to import System.Net, System.IO, System.Security.Cryptography.X509Certificates and System.Net.Security.



回答4:

JSON way

user1551788 answer works fine, however I like to do it in JSON, which is better practice instead of inserting everything in one line, I think.

The internal class 'jsonObj' is the same as the documentation requires, check the different requests you can make here

A brief description:

to: the phone to send to, insert the registrationId that you received from the phone here. delay_while_idle By using the delay_while_idle flag, notifications will be delivered once the device becomes active. (out of lock, when the user really uses the phone).

data: set data with custom key/value pairs to pass additional payload to the client app. So, you can put in any variable you want, if you like a json string that contains another object, as long as it does not exceed 4 KB.

Some that are also available that I didn't use.

collapse_key: If set, a notification that has the same collapse_key name should be overwrite the older notification (metter of good implementation at the phone side when notification is send, on the GCM server it will overwrite when the notification is pending).

time_to_live: Straight forward, how long the notification will stay alive, currently not supported for IOS.

Some other, see documentation.

internal class because I didn't need that object outside of my class, which is better for naming like 'data' that could be anything.

private void SendPostsToGCM(jsonObj jsonObj)
    {            
        string senderId = "your project number (google)";
        string apiKey = "your apiKey, found on console";

        WebRequest tRequest;
        tRequest = WebRequest.Create("https://android.googleapis.com/gcm/send");
        tRequest.Method = "post";

        tRequest.ContentType = "application/json";
        tRequest.Headers.Add(string.Format("Authorization: key={0}", apiKey));
        tRequest.Headers.Add(string.Format("Sender: id={0}", senderId));

        string jsonPostData = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj); //download Newtonsoft NuGet package

        Byte[] byteArray = Encoding.UTF8.GetBytes(jsonPostData);
        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();

        string response = sResponseFromServer;
        tReader.Close();
        dataStream.Close();
        tResponse.Close();
    }

    internal class jsonObj
    {
        public bool delay_while_idle { get; set; }
        public data data { get; set; }
        public string to { get; set; }
    }

    internal class data
    {
        public int Id { get; set; }
        public string text { get; set; }
    }

To use, simply:

    //some filtering to select some posts or whatever.
    jsonObj jsonPostData = new jsonObj()
    {
        delay_while_idle = true,
        to = registrationGCMid,
        data = new data()
        {
            Id = post.id,
            text = post.text,
        }
    };
SendPostsToGCM(jsonPostData);

Another great difference I have noticed, the google service returns a json string containing useful information, it tells how many succeeded and how many failed, etc.



回答5:

Nikunj Ganatra, you can once check out this link for your error type, maybe your application id would be wrong or other details may be incorrect.. http://developer.android.com/guide/google/gcm/gcm.html#top

Response/Description

200 Message was processed successfully. The response body will contain more details about the message status, but its format will depend whether the request was JSON or plain text. See Interpreting a success response for more details.

400 Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields (for instance, passing a string where a number was expected). The exact failure reason is described in the response and the problem should be addressed before the request can be retried.

401 There was an error authenticating the sender account.

500 There was an internal error in the GCM server while trying to process the request.

503 Indicates that the server is temporarily unavailable (i.e., because of timeouts, etc ). Sender must retry later, honoring any Retry-After header included in the response. Application servers must implement exponential back-off. The GCM server took too long to process the request.

I have just rectified it.