Normally when you install a new app that supports push notifications with Azure Notification Hub, a new token is generated after first startup. At that moment tags are registered as well.
But what if you want to update these notifications tag on a later moment, for instance after a login? Then you have to update the tag!
How can you do that?
I am using the NotificationHubSample, Microsoft has created. You can find it here:
https://github.com/xamarin/xamarin-forms-samples/tree/master/WebServices/AzureNotificationHub/NotificationHubSample
As soon as the new token is generated, we have to store it secure because we need it during update of the notification tags:
In
Android in FirebaseService.cs:
public async override void OnNewToken(string token)
{
SendRegistrationToServer(token);
await SecureStorage.SetAsync("newnotificationtoken", "true");
}
In
iOS in AppDelegate.cs:
public override async void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
try
{
Hub = new SBNotificationHub(General.ListenConnectionString, General.NotificationHubName);
// update registration with Azure Notification Hub
Hub.UnregisterAll(deviceToken, (error) =>
{
if (error != null)
{
Crashes.TrackError(new System.InvalidOperationException($"Unable to call unregister {error}"));
return;
}
var tags = new NSSet(General.SubscriptionTags.ToArray());
Hub.RegisterNative(deviceToken, tags, (errorCallback) =>
{
if (errorCallback != null)
{
Crashes.TrackError(new System.InvalidOperationException($"RegisterNativeAsync error: {errorCallback}"));
}
});
var templateExpiration = DateTime.Now.AddDays(120).ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));
Hub.RegisterTemplate(deviceToken, "defaultTemplate", General.APNTemplateBody, templateExpiration, tags, (errorCallback) =>
{
if (errorCallback != null)
{
if (errorCallback != null)
{
Crashes.TrackError(new System.InvalidOperationException($"RegisterTemplateAsync error: {errorCallback}"));
}
}
});
});
//convert it to a base64 string that can be stored and used later when you want to update the tag
string token = deviceToken.getBase64EncodedString(NSDataBase64EncodingOptions.None);
await SecureStorage.SetAsync("notificationtoken", token);
} catch (Exception ex)
{
Crashes.TrackError(ex));
}
}
Then we are going to create Dependency objects in Android and iOS.
First create an interface class in you shared project
namespace Xamarin_Support.Interfaces
{
public interface INotificationHelper
{
void UpdateToken(string token, string[] subscriptionTags);
}
}
In
Android project create a new dependency object NotificationHelper, that is based on the above interface class.
using notification_App.Droid.Helpers;
using Plugin.CurrentActivity;
using System.Threading.Tasks;
using WindowsAzure.Messaging;
using Xamarin.Forms;
using Xamarin_Support.Helpers;
using Xamarin_Support.Interfaces;
[assembly: Dependency(typeof(NotificationHelper))]
namespace notification_App.Droid.Helpers
{
public class NotificationHelper : INotificationHelper
{
public async void UpdateToken(string token, string[] subscriptionTags)
{
NotificationHub hub = new NotificationHub(General.NotificationHubName, General.ListenConnectionString, CrossCurrentActivity.Current.Activity);
//run on different thread, not on ui thread to prevent an exception
await Task.Run(() => {
//First unregister from current tags
hub.Unregister();
// register new tags with Azure Notification Hub using the token from FCM
hub.Register(token, subscriptionTags);
});
}
}
}
In
iOS project also, create a new dependency object NotificationHelper, that is based on the above interface class.
using notification_App.iOS.Helpers;
using Foundation;
using Microsoft.AppCenter.Crashes;
using System.Linq;
using WindowsAzure.Messaging;
using Xamarin.Forms;
using Xamarin_Support.Helpers;
using Xamarin_Support.Interfaces;
[assembly: Dependency(typeof(NotificationHelper))]
namespace notification_App.iOS.Helpers
{
public class NotificationHelper : INotificationHelper
{
public void UpdateToken(string token, string[] subscriptionTags)
{
SBNotificationHub Hub = new SBNotificationHub(General.ListenConnectionString, General.NotificationHubName);
NSData deviceToken = new NSData(token, NSDataBase64DecodingOptions.None);
Hub.UnregisterAll(deviceToken, (error) =>
{
if (error != null)
{
Crashes.TrackError(new System.InvalidOperationException($"Unable to call unregister {error}"));
return;
}
var tags = new NSSet(subscriptionTags.ToArray());
Hub.RegisterNative(deviceToken, tags, (errorCallback) =>
{
if (errorCallback != null)
{
Crashes.TrackError(new System.InvalidOperationException($"RegisterNativeAsync error: {errorCallback}"));
}
});
});
}
}
}
Now you are ready to update the notification tags, whereever you want, for instance after a succesfull login:
INotificationHelper notificationHelper = DependencyService.Get<INotificationHelper>();
//get the sored token
string notificationToken = await SecureStorage.GetAsync("notificationtoken");
//create new tag array
string[] subscriptionTags = new string[] { customerId };
//update tags
notificationHelper.UpdateToken(notificationToken, subscriptionTags);