Search code examples
c#azurexamarin.iosazure-notificationhub

How to retrieve a PNS Handle from the Platform Notification Service?


I have an Xamarin.iOS application that is connecting an Azure backend service and I want my service to send notifications to the client applications.

The Microsoft documentation explains how to set up the Notification Hub for different scenario. I think I am getting most of it, however I am not sure I understood the very first part, which is for the iOS application to Retrieve PNS Handle from the Platform Notification Service, as shown in the following picture:

enter image description here

It looks like this is some task that must be performed by the client application alone and then communicate this to the backend service for the registration.

I have a feeling that it happens at the 10th step of this section, when iOS calls the application back on the method RegisteredForRemoteNotifications. In that callback, the application is given a deviceToken:

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    Hub = new SBNotificationHub(Constants.ListenConnectionString, Constants.NotificationHubName);

    Hub.UnregisterAllAsync (deviceToken, (error) => {
        if (error != null)
        {
            System.Diagnostics.Debug.WriteLine("Error calling Unregister: {0}", error.ToString());
            return;
        }

        NSSet tags = null; // create tags if you want
        Hub.RegisterNativeAsync(deviceToken, tags, (errorCallback) => {
            if (errorCallback != null)
                System.Diagnostics.Debug.WriteLine("RegisterNativeAsync error: " + errorCallback.ToString());
        });
    });
}

Question

Is that deviceToken the PNS Handle that I need to send to the backend service to start the registration process? If not, how am I supposed to contact the PNS to get the Handle?


Solution

  • The information is in the documentation but not in an obvious form for a C# developer.

    In Objective-C, the deviceToken is provided by the iOS application, as mentioned by @LucasZ, after it got registered against the PNS.

    However I can't just send this deviceToken right away as it will not be accepted by the AppleRegistrationDescription class used in my Service.

    It took me a while to get more familiar with Objective-C to figure out that this token was actually transformed before being sent to Azure:

    NSSet* tagsSet = tags?tags:[[NSSet alloc] init];
    
    NSString *deviceTokenString = [[token description]
            stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    
        deviceTokenString = [[deviceTokenString stringByReplacingOccurrencesOfString:@" " withString:@""] uppercaseString];
    

    I have implemented something similar in C#:

    public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        string pnsHandle = deviceToken.Description
                                      .Replace("<", string.Empty)
                                      .Replace(">", string.Empty)
                                      .Replace(" ", string.Empty)
                                      .ToUpper(); 
    
        Hub = new SBNotificationHub(Constants.ListenConnectionString, Constants.NotificationHubName);
    
        Hub.UnregisterAllAsync (pnsHandle, (error) => 
        {
            if (error != null)
            {
                System.Diagnostics.Debug.WriteLine("Error calling Unregister: {0}", error.ToString());
                return;
            }
    
            // In my use case, the tags are assigned by the server based on privileges.
            NSSet tags = null;
    
            Hub.RegisterNativeAsync(pnsHandle, tags, (errorCallback) => 
            {
                if (errorCallback != null)
                    System.Diagnostics.Debug.WriteLine("RegisterNativeAsync error: " + errorCallback.ToString());
            });
        });
    }
    

    To answer my question, yes, the deviceToken is the PNS Handle but it must be formatted.