Give your app Toast
Adding push notifications to your UWP app is actually quite simple. There’s quite a few different methods. This is the one that I found to be the easiest to implement with the minimum of fuss.
For this tutorial you will need the following:
- an existing VB.net UWP project that has been published to the store
- an existing ASP.net web service
- an active Azure account
Setting up the Notification Hub
- Log into your developer account at developer.microsoft.com and go to your dashboard
- Click on your App and expand the Services section. Click on Push Notifications followed by WNS/MPNS
- Amongst all the text under Push Notifications there is a link for Live Services site, click on this.
- You will now see the live services registration page for your app.
- From this page you will need the current Application Secret:
- You will also need the Package SID
- Log in to your Azure account and create a Notification Hub if you don’t already have one
- Once created, select the Notification Hub in the Azure Portal
- Under the Manage section click on Notification Services
- Select Windows (WNS)
- Paste in the Package SID from step 6
- Paste in the Application Secret from step 5 as the Security Key and click on Save
- Now click on Access Policies under Manage and take note of two prebuilt policies.
You will need both Connection Strings (DefaultListenSharedAccessSignature and DefaultFullSharedAccessSignature) later on:
Registering Your App with the Notification Hub
Your app needs to register itself with the Notification Hub. This can be done when your app starts but if you want to send notifications to unique users you will need to do this after your user has logged in to your app. Once your app has registered itself your device will be set up to receive notifications even if the app is not running.
For simplicity we’ll first look at registering with the notification hub without unique user notifications. We’ll add this in later on.
- Open your UWP in visual studio
- Open the NuGet Package Manager and install WindowsAzure.Messaging and WindowsAzure.Messaging.Managed
- Open App.xaml.vb in the IDE and add the following imports
Imports Windows.Networking.PushNotifications Imports Microsoft.WindowsAzure.Messaging
- Add the following Function to App.xaml.vb
Private Async Function InitNotificationsAsync() As Task Try ' Get a channel URI from WNS. Dim channel As PushNotificationChannel = Await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync() Dim hub = New NotificationHub("HUBNAME", "ENDPOINT") Dim result As Microsoft.WindowsAzure.Messaging.Registration = Await hub.RegisterNativeAsync(channel.Uri,"MYAPP") ' Displays the registration ID so you know it was successful If result.RegistrationId IsNot Nothing Then Dim dialog = New MessageDialog("Registration successful: " + result.RegistrationId) dialog.Commands.Add(New UICommand("OK")) Await dialog.ShowAsync() End If Catch ex As Exception End Try End Function
- On line 5 we create the Hub object. You will need to replace the two strings HUBNAME and ENDPOINT.
HUBNAME is the name you gave the notification hub in Azure
ENDPOINT is the DefaultListenSharedAccessSignature you copied from the Access Policy for the hub in Azure
- Add a call to InitNotificationsAsync from the OnLaunched sub in App.xaml.vb. At the start of the sub is fine.
- If you now run your project you should see a dialog box with your registration id.
- Close your app
- From Azure, select your Notification Hub again and click on Test Send
- Make sure the Platforms is set to Windows (even if you are developing for mobile select Windows not Windows Phone)
- Set the Notification Type to Toast
- In the Send to Tag box type MYAPP
- Click the Send button. You should receive a toast message.
What’s happening here is that Azure will send a test message to 10 random registered devices. Because you’ve only registered the one device at this stage you will receive the test message.
- If you click on the toast message your app should start
Registering Your Web Service with the Notification Hub
If you check back at the step earlier where we sent a test message you will that the Payload is in XML. Toasts (and Tiles) are built using XML files that are sent to the device.
There is an excellent free app you can install from the windows app store called Notifications Visualizer (https://www.microsoft.com/store/apps/9nblggh5xsl1). The app helps you design the XML you need to create Toasts and Tiles.
For documentation on creating the XML and what features are possible see this page: https://msdn.microsoft.com/en-us/windows/uwp/controls-and-patterns/tiles-and-notifications-create-adaptive-tiles
Typically you’ll want your web service to create notifications when the user performs a task or if a scheduled task is performed. In this example we are going to create a function you can use to send a Toast message. I like to add this function to a class but you can add it into your controller for example. I’m also using a prebuilt XML file to easily send different Toast content.
- Open your ASP.Net webservice? solution in visual studio
- Open the NuGet Package Manager and install Microsoft.Azure.NotificationHubs
- Add a folder to the root level of your web service called Notifications
- Create a new xml file called BreakingNews.xml in the Notifications folder
- Copy the following xml into the BreakingNews.xml file and publish it to your webserver
<toast launch="!!CMD!!"> <visual> <binding template="ToastGeneric"> <text>!!TITLE!!</text> <text>!!ALERTTEXT!!</text> <text placement="attribution">!!ATTR!!</text> </binding> </visual> </toast>
The content enclosed in !! will be replaced with content we pass in to?our function
- Add the following Imports to your class, page or controller
- Add the following function to your class, page or controller
Public Shared Async Function SendToastAlert(ByVal Tag As String, ByVal Title As String, ByVal AlertText As String, ByVal Attribution As String, ByVal CMD As String) As System.Threading.Tasks.Task(Of Boolean) Try Dim outcome As Microsoft.Azure.NotificationHubs.NotificationOutcome = Nothing Dim hub As NotificationHubClient = NotificationHubClient.CreateClientFromConnectionString("ENDPOINT", "HUBNAME") Dim ServerPath As String = HttpContext.Current.Server.MapPath("/") Dim header_Reader As IO.StreamReader = New IO.StreamReader(ServerPath & "Notifications\BreakingNews.xml") Dim toast As String = header_Reader.ReadToEnd() toast = toast.Replace("!!TITLE!!", Title) _ .Replace("!!ALERTTEXT!!", AlertText) _ .Replace("!!ATTR!!", Attribution) _ .Replace("!!CMD!!", CMD) outcome = Await hub.SendWindowsNativeNotificationAsync(toast, Tag) Return True Catch ex As Exception Return False End Try End Function
- Again on line 4 we create the Hub object. You will need to replace the two strings HUBNAME and ENDPOINT.
HUBNAME is the name you gave the notification hub in Azure
ENDPOINT is the DefaultFullSharedAccessSignature you copied from the Access Policy for the hub in Azure
(IMPORTANT! make sure you use the full access end point and not the listen one)
- From your code call the SendToastAlert function. Make sure you pass in “MYAPP” as the tag parameter.
Sending toasts to unique users
If you look back at step 4 when we added the InitNotificationAsync function to our UWP app you will see on line 6 I used MYAPP as a tag to register the app with the notification hub. You can replace this tag with whatever you like to uniquely identify the registration with the hub. This could be a user id or device id depending upon what your usage requirements are.
If you are registering a user you will need to call the hub registration after you have determined who the user is. You can then use your unique identifier in the Tag box when sending a Test via the Azure portal.
Sending Commands from a toast to your App
You’ll notice in my SendToastAlert function there is a CMD parameter. This is a string in the format simular to a query string, i.e. action=open&value=1
When a user clicks on the toast this command string is passed to your app. Responding to the command depends upon wether your app is actually already running or not.
If you app hasn’t started then you can respond to the command from within the OnLaunched sub in App.xaml.vb
Protected Overrides Async Sub OnLaunched(e As Windows.ApplicationModel.Activation.LaunchActivatedEventArgs) 'how the app was launched debug.writeline(e.Kind) 'the command string passed to the app debug.writeline(e.Arguments) End Sub
However if your app is already running then you will need to override the OnActivated sub by pasting the following into App.xaml.vb
Protected Overrides Async Sub OnActivated(e As IActivatedEventArgs) If e.Kind = ActivationKind.ToastNotification Then Dim ToastArgs As ToastNotificationActivatedEventArgs = e debug.writeline(ToastArgs.Kind) debug.writeline(ToastArgs.Argument) End If End Sub
I’ve found the best way to get the data from the command string is to use the WwwFormUrlDecoder like so:
Dim decoder As New WwwFormUrlDecoder(e.Arguments) Dim CMD As String = decoder.GetFirstValueByName("action") Dim VALUE As String = decoder.GetFirstValueByName("value")