Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to send Android push notifications via GCM on C# .Net

I'm new to all Android GCM push notifications and I have read stack posts but couldn't get a straight answer.I have also read Create push notification in android to get a better understanding of how GCM works. I have also used the gcm-demo-server and gcm-demo-client provided by the SDK. However, here are my doubts and what I have tried so far:

  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?

like image 415
Pavan Welihinda Avatar asked Apr 27 '13 04:04

Pavan Welihinda


4 Answers

Refer Code:

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

Referance Link:

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

like image 145
Freelancer Avatar answered Nov 20 '22 02:11

Freelancer


Code looks bit long but it works. I just sent a push notification to my phone after struggling 2 days by implementing the following code in C# project. I referred a link regarding this implementation, But couldn't find it to post here. So will share my code with you. If you want to test the Notification online you may visit to this link.

note : I have hardcorded apiKey, deviceId and postData, please pass the apiKey,deviceId and postData in your request and remove them from the method body. If you want pass message string also

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

You may not familiar with words like apiKey, deviceId. Dont worry i will explain what are they and how to create those.

apiKey
What & why :This a key that will be used when sending requests to GCM server.
How to create : Refer this post

deviceId
What & why : This id also known as RegistrationId. This is a unique id to identify the device. When you want to send a notification to a specific device you need this id.
How to create: This depends on how you implement the application. For cordova i used a simple pushNotification Plugin You can simply create a deviceId/RegistrationId using this plugin. To do that you need to have a senderId. Google how to create a senderId it is really simple =)

If anyone needs some help leave a comment.

Happy Coding.
-Charitha-

like image 35
Charitha Goonewardena Avatar answered Nov 20 '22 02:11

Charitha Goonewardena


Just for the information for new visitors on this post, if you want to send same message to multiple devices then simply send comma separated device ids in registration_id parameter of request.

Here is a nice article on this http://www.codewithasp.net/2015/11/send-message-gcm-c-sharp-single-multiple.html

like image 3
Nikhil Gaur Avatar answered Nov 20 '22 02:11

Nikhil Gaur


This never worked for me and it is hard to debug plus passing a list of registration token is not clear -would expect passing a string array instead of comma separated string - , the fact that this is very simple post request i created my own class with a method that return the server response, and it works very well:

Usage

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

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

Class

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

}
like image 2
Mina Gabriel Avatar answered Nov 20 '22 02:11

Mina Gabriel