Appearance
Migrating from Urban Airship (UA) to PushSharp
December 4, 2014
When Urban Airship (UA) announced back in June that they would be canceling their free tier for push notifications I started looking at other free & paid alternatives (e.g. Parse, Azure and others). However, ultimately I decided to host the push notifications myself using PushSharp.
Architecture
If you’re not familiar with PushSharp, it is a server side library for sending push notifications to various platforms.
The migration was really pretty easy and involved these steps:
- Update server software that sends out push notifications to use the PushSharp libraries.
- Update mobile apps (in my case this was just for the iOS and Android platforms)
- Implement a mitigation strategy to handle users on old versions of the Android application
Updating Server Software
Urban Airship provides a REST API to send push notifications:
csharp
WebRequest request = WebRequest.Create("https://go.urbanairship.com/api/push/");
request.Method = "POST";
request.ContentType = "application/json";
request.Credentials = new System.Net.NetworkCredential("user", "pass");
string body = GenPayload(deviceToken, message, id, id2);
StreamWriter sr = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
sr.Write(body);
sr.Close();
I replaced that code with something that looks like this:
csharp
if (type == PushType.Apple)
{
var not = new AppleNotification().ForDeviceToken(deviceToken).WithAlert(message).WithCustomItem("id", id.ToString());
if (!String.IsNullOrEmpty(id2) && id2 != "-1")
not.WithCustomItem("id2", id2);
myPushBroker.QueueNotification(not);
}
else if (type == PushType.UAGCM) // GCM via UA , obsolete
{
SendAndroidPushViaUA(deviceToken, message, id, id2);
}
else if (type == PushType.GCM)// GCM
{
var gcm = new GcmNotification().ForDeviceRegistrationId(deviceToken).WithJson(GenPayloadAndroid(message, id, id2));
myPushBroker.QueueNotification(gcm);
}
If you look at the sample in the GitHub repository you’ll see there is some setup of the Push Broker that needs to be done prior to sending any messages. If you are hosting your server code in a windows service you could put that in your main program. In my case I’m hosting the Push Broker inside of IIS and thus have put all of that code into my Application_Startup method.
Note: you can update and deploy the server software prior to updating your apps.
A Note about Urban Airship notifications for Android
My sample code above includes a case for Urban Airship Android messages. The reason for this is that the device token you get from their APIs is not actually a Google Cloud Messaging (GCM) device token but rather an Urban Airship generated token. This is unfortunate as it means you’ll need to continue sending some push notifications via the Urban Airship REST API until all of your users are transitioned over to your new app.
Updating Mobile Applications
Updating my iOS application was pretty trivial as I just had to remove the code that registered my device with Urban Airship. Nothing else needed to be changed as the device token you deal with is a standard APNS device token and not an Urban Airship token. Additionally, as the messages that are sent by PushSharp on the server are identical to the messages sent via Urban Airship I didn’t have to change my code that parsed the notification.
Updating my Android app was a little more involved.
Remove the Urban Airship binding library as well as any calls to Urban Airship.
Add the GCM Client component to the project.
Edit the AndroidManifest.xml and remove all lines that deal with Urban Airship.
Edit the startup application code (e.g. MainApplication.cs) and remove any calls to Urban Airship and replace with GCM.Client calls:
Old:
csharp
AirshipConfigOptions options = AirshipConfigOptions.LoadDefaultOptions(this);
UAirship.TakeOff(this, options);
PushManager.Shared().IntentReceiver = Java.Lang.Class.FromType(typeof(IntentReceiver));
BuildCustomNotification();
PushManager.EnablePush();
var apid = PushManager.Shared().APID;
New:
csharp
GcmClient.CheckDevice(this);
GcmClient.CheckManifest(this);
//Call to Register the device for Push Notifications
GcmClient.Register(this, GcmBroadcastReceiver.SENDER_IDS);
- Remove the BroadcastReceiver service and replace it with a service as shown in the GCM.Client sample. Migrate any code from the OnReceive handler in the BroadcastReceiver class to the OnMessage handler in GcmService.
One extra piece of work that I had to do was because I was using a Urban Airship specific class for displaying notifications (CustomPushNotificationBuilder). I replaced that with Notification.Builder.
Mitigation Strategy
To handle the fact that Urban Airship uses their own device tokens on Android, my approach was to treat device registrations using GCM.Client as a new device type on my backend (and thus leave in place Urban Airship GCM device registrations). Thus until the end of the year my server software will continue to send push notifications to any users that are still on an older version of the Android app via the Urban Airship REST API. Users that install the new application and subscribe for push notifications will receive their notifications via PushSharp. I’ll continue to monitor how many devices are still on Urban Airship as I approach the year end and may choose to send a broadcast notification to those devices to tell them to upgrade. After 12/31 I will update the server software to quit handling Urban Airship GCM tokens.
Final Thoughts
If you’re thinking about adding push notifications to your app but weren’t sure what to do take a look at PushSharp. Jon Dick has done a great job with the software and continues to support and enhance it (he tells me he is working on a new and improved version that will be out before too long!)