Rudi Visser Rudi Visser - 22 days ago 6
iOS Question

Notification Hub Devices disappearing after Push (APNS)

We have an Azure Notification Hub set up, with APNS Configured in Production Mode, using our Production APNS Certificate.
We register our test devices (using TestFlight / Production build, and certificate) to APNS, and then to ANH with a tag

dealer-1
. We can send notifications using our production certificate and registered Device ID with success when using APNS directly, however, when we use 'Test Send' we get a 'Successful send' to 1 device (or however many we have registered). The notification is not received. If we then run 'Test Send' again, the are 0 devices to send to.

In the logs, we see 'APNS Errors' per device, per test send. I cannot see any way to view what the errors actually are though so this is an absolutely useless metric.

I have ran through all the troubleshooting steps and confirmed many times that everything is setup in 'Production'.

Having reviewed other questions, the answers have been along the lines of:


  • .. registering a sandbox certificate and then changing it to production. Unfortunately we created this hub from scratch as Production in an attempt to work around that potential issue.

  • .. registering sandbox devices (and thus tokens) against the production certificate. Unfortunately I have controlled this closely and ensured that we are only registering TestFlight builds (thus Production) against the ANH.

  • .. uploading the wrong certificate. I have confirmed with the Push Notification Tester, as above, that the certificate is correct (thumbprint confirmed, re-uploaded, etc) and works to send to the devices via Production APNS endpoint.



The resource name is: eight-technology/react-push-notification-hub

In-app registration process is as follows:


  • Device registers for push notifications

  • Registration event is handled in iOS Project (AppDelegate event)..

    public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
    //base.RegisteredForRemoteNotifications(application, deviceToken);
    App.ConfigurePushNotifications(deviceToken.ToString());
    }

  • ConfigurePushNotifications is in the XF Shared Project..

    public static void ConfigurePushNotifications(string deviceToken)
    {
    var azureComm = DependencyService.Get<Interop.IAzureCommunication>();
    azureComm.RegisterForPushTags(
    "sb://eight-technology.servicebus.windows.net/",
    ".. token ..",
    "react-push-notification-hub",
    deviceToken,
    StateManager.SelectedNodes.Select(m => "dealer-" + m).ToArray());
    }

  • The implementation is pretty much as per the sample code provided (contained in iOS project)

    public class AzureCommunication : DealerwebReact.Interop.IAzureCommunication
    {
    public void RegisterForPushTags(string url, string key, string hubName, string deviceToken, string[] tags)
    {
    var cs = SBConnectionString.CreateListenAccess(new NSUrl(url), key);

    var hub = new SBNotificationHub(cs, hubName);
    hub.RegisterNativeAsync(deviceToken, new NSSet(tags), err =>
    {
    if (err != null)
    Console.WriteLine("Error: " + err.Description);
    else
    Console.WriteLine("Success");
    });
    }
    }


Answer

After a frustrating few days, and thanks to the help of Nikita G. and hvaughan3 I finally got to the root cause of my issue. As anticipated it wasn't any of the issues actually outlined, but was to do with the way we handled the cross-plat aspect of the registrations with Xamarin Forms.

That is, we stored our token in a class as a string. The NSData that is received as part of the iOS Device registration in RegisteredForRemoteNotifications has a ToString() method that is incompatible with sending to ANH. Furthermore, RegisterNativeAsync method from the Azure library requires an NSData which I assume Xamarin can morph a string into without warning or error, hence it was unknown that the two were somewhat incompatible.

Basically, to maintain cross platform functionality, we are now simply passing the token around as an object and performing the translation back to the original type in the platform-specific implementation of our push configuration method.

Our registration method now looks like this, note the explicit use of the NSData type so that it remains untouched whilst passing through the Xamarin Forms layer:

    public void RegisterForPushTags(string url, string key, string hubName, object deviceToken, string[] tags)
    {
        var cs = SBConnectionString.CreateListenAccess(new NSUrl(url), key);

        var hub = new SBNotificationHub(cs, hubName);
        hub.RegisterNativeAsync((NSData)deviceToken, new NSSet(tags), err =>
        {
            if (err != null)
                Console.WriteLine("Error: " + err.Description);
            else
                Console.WriteLine("Success");
        });
    }