Search code examples
azurexamarin.iosxamarin.androidcross-platformazure-notificationhub

.Net Mobile Service Back-End for Notification Hub


I am currently writing a mobile application with Xamarin for Android and will be adding iOS once my company purchases a Mac so that I can start developing the iOS portion. I am currently trying to write a .Net Mobile Services back-end for Azure Notification Hub that will allow me to register the devices from the back end as well as send push notification to a specific user, and/or all users.

I have followed the Azure documentation all the way through Getting Started With Notification Hub and have successfully performed a single platform push. Moving beyond this example however is where I get stuck. Every example beyond this point completely drops Android support and only focuses on Windows Phone and iOS. I have watched a few Channel 9 videos regarding this subject and again it's all Windows Phone, Windows 8, and iOS based.

Does anyone have an example of a .Net Mobile Service back-end for Azure Notification Hub that will register the device to the notification hub from the back-end? Thank you for your time.


Solution

  • I don't have sample code on GitHub yet, but here's a gist of how to get NotificationHub working on Android.

    using Microsoft.ServiceBus.Notifications;
    using Newtonsoft.Json;
    
    public class AndroidNotificationHub
    {
        private readonly NotificationHubClient _hubClient;
    
        public AndroidNotificationHub()
        {
            const string cn = "YourConnectionStringHere";
            const string hubPath = "YourHubPathHere";
            _hubClient = NotificationHubClient.CreateClientFromConnectionString(cn, hubPath);
        }
    
        public async Task<RegistrationDescription> Register(string platform, string installationId, string registrationId, string userName)
        {
            // Get registrations for the current installation ID.
            var regsForInstId = await _hubClient.GetRegistrationsByTagAsync(installationId, 100);
    
            var updated = false;
            var firstRegistration = true;
            RegistrationDescription registration = null;
    
            // Check for existing registrations.
            foreach (var registrationDescription in regsForInstId)
            {
                if (firstRegistration)
                {
                    // Update the tags.
                    registrationDescription.Tags = new HashSet<string>() { installationId, userName };
    
                    // We need to handle each platform separately.
                    switch (platform)
                    {
                        case "android":
                            var gcmReg = registrationDescription as GcmRegistrationDescription;
                            gcmReg.GcmRegistrationId = registrationId;
                            registration = await _hubClient.UpdateRegistrationAsync(gcmReg);
                            break;
                    }
                    updated = true;
                    firstRegistration = false;
                }
                else
                {
                    // We shouldn't have any extra registrations; delete if we do.
                    await _hubClient.DeleteRegistrationAsync(registrationDescription);
                }
            }
    
            // Create a new registration.
            if (!updated)
            {
                switch (platform)
                {
                    case "android":
                        registration = await _hubClient.CreateGcmNativeRegistrationAsync(registrationId, new[] { installationId, userName });
                        break;
                }
            }
    
            return registration;
        }
    
        // Basic implementation that sends a notification to Android clients
        public async Task<bool> SendNotification(int id, string from, string text, string tag)
        {
            try
            {
                var payload = new
                {
                    data = new
                    {
                        message = new
                        {
                            // these properties can be whatever you want
                            id,
                            from,
                            text,
                            when = DateTime.UtcNow.ToString("s") + "Z"
                        }
                    }
                };
    
                var json = JsonConvert.SerializeObject(payload);
    
                await _hubClient.SendGcmNativeNotificationAsync(json, tag);
    
                return true;
            }
            catch (ArgumentException ex)
            {
                // This is expected when an APNS registration doesn't exist.
                return false;
            }
        }
    
        public async Task<bool> ClearRegistrations(string userName)
        {
            // Get registrations for the current installation ID.
            var regsForInstId = await _hubClient.GetRegistrationsByTagAsync(userName, 100);
    
            // Check for existing registrations.
            foreach (var registrationDescription in regsForInstId)
            {
                // We shouldn't have any extra registrations; delete if we do.
                await _hubClient.DeleteRegistrationAsync(registrationDescription);
            }
            return true;
        }
    }
    

    Your Android client will need to call your backend's registration API during startup. I have an MVC action for this.

    [HttpPost]
    public async Task<ActionResult> Register(string platform, string installationId, string registrationId, string userName)
    {
        try
        {
            var hub = new AndroidNotificationHub();
            var registration = await hub.Register(platform, installationId, registrationId, userName);
            return Json(registration);
        }
        catch (Exception ex)
        {
            return Content(ex.ToString());
        }
    }
    

    Once the mobile client has registered, you can then start sending notifications from your backend, by calling the SendNotification method.

    Hope this points you in the right direction.