How to send push notifications to mobile devices with ServiceStack and PushSharp

PushSharp is a c# library, useful for sending Push Notifications to a very large range of devices (iOS, Android, Windows Phone, Chrome, Amazon, etc.). It allows you to generalize the sending of push notifications, without worrying about the type of device that will receive it.

We’ll use ServiceStack as a framework for building a simple webservice.

Full code available on Github

NuGet packages required:

SELF HOST APPLICATION
We’re going to use a self-host ServiceStack application, but the same concept works also in the other configurations

After creating an empty self-host ServiceStack application (https://github.com/ServiceStack/ServiceStack/wiki/Self-hosting), we’ll configure it.

First, we’ll create a new instance of PushSharp.PushBroker, that handles encoding and sending push notifications to notification providers.

static void Main(string[] args)
{
   ....
   var pushBroker = new PushBroker();
   pushBroker.OnNotificationSent += (sender, notification) =>
   {
      Console.Write("OK");
   };
   pushBroker.OnNotificationFailed += (sender, notification, error) =>
   {
      Console.Write(error.Message);
   };
   pushBroker.OnChannelException += (sender, channel, error) =>
   {
      Console.Write(error.Message);
   };

   var appHost = new Program.AppHost(pushBroker)
       .Init()
       .Start(listeningOn);

   Console.WriteLine("AppHost Created at {0}, listening on {1}",
   DateTime.Now, listeningOn);

   Console.ReadKey();
}

In the AppHost configuration we’ll register the instance of Push Broker in the container. We’ll configure only the GCM provider. For other providers, please see the PushSharp Wiki at https://github.com/Redth/PushSharp/wiki

public class AppHost : AppSelfHostBase
{
   private PushBroker _pushBroker;
   
   public AppHost(PushBroker pushBroker)
                : base("HttpListener Self-Host", typeof(PushService).Assembly)
   {
      _pushBroker = pushBroker;
   }

   public override void Configure(Funq.Container container)
   {
      _pushBroker.RegisterGcmService(new GcmPushChannelSettings(AppSettings.GetString("AndroidServerKey")));
            
      container.Register(c => _pushBroker).ReusedWithin(ReuseScope.Container);
      container.Register(new ServerSettings {ApiKey = AppSettings.GetString("ApiKey")});
      }
}

ServerSettings is a simple class that helps us to get the API Key value in our service.

public class ServerSettings
{
  public string ApiKey { get; set; }
}

DTO

This is the DTO used for sending Push Requests. With the secret APIKey field in the PushRequest class, it’s possible to restrict the access to our pushservice, without having to set up complex authentication systems.

[Route("/push")]
 public class PushRequest : IReturn<PushResponse>
 {
   public string ApiKey { get; set; }
   public PushNotification[] Notifications { get; set; }
 }

public class PushResponse
{
   public string Result {get; set;}
}

PushNotification class has:

  • A Provider enum field that identifies the type of device that will receive the notification;
  • The Push Id (supplied by notification provider);
  • A string Data field (the content of notification that we will send to device).

The PushId is a generic string that identifies one device. For Apple devices is the device token, for Android is the GCM device registration Id, for Windows Phone is the push notification uri.

 public class PushNotification
 {
    public Provider Provider { get; set; }
    public string PushId { get; set; }
    public string Data { get; set; }
 }

SERVICE
And this is the service class.

public class PushService : Service
{
    public ServerSettings Settings { get; set; }
    public PushBroker PushBroker { get; set; }

    public object Any(PushRequest request)
    {
        //Check if the Api Key provided by client match the key saved in app.config
        if (request.ApiKey == Settings.ApiKey)
         {
             foreach (var pushNotification in request.Notifications)
              {
               switch (pushNotification.Provider)
               {
                  case Provider.Apple:
                       //NOTE: Apple Notification Payload has 256 chars limit.
                       PushBroker.QueueNotification(new AppleNotification().ForDeviceToken(pushNotification.PushId).WithCustomItem("data", HttpUtility.UrlDecode(pushNotification.Data)));
                       break;

                  case Provider.Android:
                       PushBroker.QueueNotification(new GcmNotification().ForDeviceRegistrationId(pushNotification.PushId)
                            .WithJson(HttpUtility.UrlDecode(pushNotification.Data)));
                       break;

                  case Provider.WindowsPhone:
                       PushBroker.QueueNotification(new WindowsPhoneRawNotification().ForEndpointUri(new Uri(pushNotification.PushId))
                              WithRaw(HttpUtility.UrlDecode(pushNotification.Data)));
                       break;
                 }
            }

            return new PushResponse() {Result = request.Notifications.Length + " notifications encoded"};
        }

        throw new HttpError(HttpStatusCode.Unauthorized, "Invalid Api Key");
    }
}

You can get full source code on my Github

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s