Forum Xamarin.iOS

Xamarin iOS Azure Notification Hubs with Xcode 11.3 and iOS 13.3 Issue

gadeweevergadeweever Member ✭✭

Hey we're hitting this issue on all devices with iOS v13.3.1 with Xamarin IOS. It seems to be related to a change in the format for the device token:

iOS 13.3:
{length = 32, bytes = 0xf1d219ab c4aab6f4 e0408ae2 8a6e9a5c ... c6ddccbb 6a63fe2f }

iOS 12:

We are unsure if there is an underlying issue with the SDK, or out of our own fault, but we are using Xamarin.Azure.NotificationHubs.IOS v2.0.4. Registration happens client side on the device.

Originally we had this:

        public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
        {
            _notificationDelegate.Register(_user.UserId, deviceToken);
        }
public void Register(string userID, NSData deviceToken)
        {
            _hub = new SBNotificationHub(
               Configuration.Configuration.NOTIFICATION_HUB_CONNECTION_STRING,
               Configuration.Configuration.NOTIFICATION_HUB_NAME);

            _hub.UnregisterAll(deviceToken, (unregisterError) => {
                if (unregisterError != null)
                {
                    _handler.LogError($"UnregisterAll error: {unregisterError.ToString()}");
                    return;
                }

                _handler.LogInfo($"UnregisterAll complete for user: {userID}. Starting RegisterNative");

                var tags = new NSSet($"username:{userID}");
                _hub.RegisterNative(deviceToken, tags, (registerError) =>
                {
                    if (registerError != null)
                    {
                        _handler.LogError($"RegisterNative error: {registerError}");
                    }
                    else
                    {
                        _handler.LogInfo($"RegisterNative registered: {deviceToken} for user ID: {userID}");
                        IsRegistered = true;
                    }
                });
            });
        }

This does not work anymore. RegisterNative does not get called so the device never appears in the notification hub. Given the new formats and form posts I've read online, the new code is as follows:

 public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
        {
            byte[] token = deviceToken.ToArray();
            string registrationToken = BitConverter.ToString(token).Replace("-", "");

            _notificationDelegate.Register(_user.UserId, NSData.FromString(registrationToken));
        }

In this case, the device gets registered but is deleted immediately on using the TEST SEND feature in azure notification hubs, presumably because the registration is actually invalid with the conversion. Is this a valid way to register iOS 13.3 devices with Notification Hubs, or is something else up? Note: our iOS 13.1 devices running the app built against Xcode 10 do work, and so do our iOS 12 devices.

Best Answer

  • gadeweevergadeweever Member ✭✭
    Accepted Answer

    Hi @ColeX,

    This doesn't seem to work either. The call to UnregisterAllAsync never completes and no exceptions are thrown. At least in the synchronous case they execute. However, we got this working after a couple days of madness.

    TL;DR:

    This works (or used to):

    • iOS 13 and all releases before
    • App built with Xcode 10
    • Certificate-based authentication in Azure Notification Hubs
    • Xamarin.Azure.NotificationHubs.iOS v1.2.5.2

    This also works (and currently still does):

    • iOS 13 and all releases before
    • App built with Xcode 11
    • Token-based authentication in Azure Notification Hubs
    • Xamarin.Azure.NotificationHubs.iOS v2.0.4

    Gotchas

    • No other configuration of resources/SDKs worked. We tried a matrix, a very large matrix, and they don't work.
    • The same token key cannot be used for both production and sandbox in the Notification Hub UI. Also, switching them breaks the other environment.

    If you're interested

    We had an iOS 13.1 device receiving notifications in December. We released a couple new version of our app, and they haven't gotten notifications since, but they only noticed after we released several newer version.

    At the time we were still on Xamarin.Azure.NotificationHubs.iOS v1.2.5.2, so we thought, "Oh something is wrong with iOS 13? just roll back to a previous version". This didn't work because they didn't roll back far enough.

    So we tried the bit conversion method below:

    byte[] token = deviceToken.ToArray();
    string registrationToken = BitConverter.ToString(token).Replace("-", "");
    

    We handed off this string to RegisterNativeAsync from V1.2.5.2 and the device was registered in notification hubs. When we tried to do a test send, it passed, but removed the registration and silently failed for iOS 13 devices only. iOS 12 devices worked with the conversion.

    After that, we scratched our heads (not literally), and updated to V2.0.4. We kept the conversion and tried again. Same issue: The registration exists until you try to send something to it.

    Then we looked at the documentation and saw we were missing the call to RegisterTemplate which was not necessary in V1.2.5.2. We still don't actually know what this really does and why it is in the documentation now but we will be investigating more later. Another migration issue. We added this. Still the same issue.

    Then we remembered that, sometime in the last month, we updated our build machines to Catalina and XCode 11. This is what actually broke everything (presumably), however it is not immediately clear why updating to a newer version of Xcode should have an impact on the validity of a registration, given that we were already doing the conversion.

    We came across this statement in the Azure documentation:

    "Apple now requires that developers identify notifications as an alert or background notifications through the new apns-push-type header in the APNS API. According to Apple's documentation: "The value of this header must accurately reflect the contents of your notification's payload. If there is a mismatch, or if the header is missing on required systems, APNs may return an error, delay the delivery of the notification, or drop it altogether."

    We thought "but this doesn't explain why the iOS 13 device isn't receiving notifications." However, maybe it affects new registrations? Additionally, the documentation states:

    "Remember that you must configure Azure Notification Hubs to use token-based authentication to set the required header; for more information, see Token-based (HTTP/2) Authentication for APNS."

    We were still using cert-based auth. We decided to switch to token based authentication and the new registrations were happy.

    I guess the issues came about from multiple solutions around mutliple different versions. We are not doing the bit conversion on either device, and everything seems to be okay.

    So far.

    @ColeX no further triage needed however, if you know anyone on the Xamarin/Hubs team, I'd love to talk with them and work on the documentation that's currently available since it has a number of mistakes, is fragmented, and is omits quite a few requirements for V1.x -> V2.x migration.

    The final code:

    public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        try
        {
            var successfulRegistration = _notificationDelegate.Register(_user.UserId, deviceToken).Result;
            if (!successfulRegistration)
            {
                /// log this
            }
        }
        catch(Exception e)
        {
            /// log this
        }
    }
    
    /// originally this used the async methods from V2.0.4.
    /// The never returned, even with .ConfigureAwait(false)
    /// The method signature retains Task<bool> even though it is not required
    public async Task<bool> Register(string userID, NSData deviceToken)
    {
        var error = false;
        try
        {
            _hub = new SBNotificationHub(
                Configuration.Configuration.NOTIFICATION_HUB_CONNECTION_STRING,
                Configuration.Configuration.NOTIFICATION_HUB_NAME);
    
            /// we add a username with our registrations.
            var tags = new NSSet(CloudNotificationConstants.DefaultSubscriptionTag, $"username:{userID}");
    
            _hub.UnregisterAll(deviceToken, (errorCallback) => {
                if (errorCallback != null)
                {
                    /// log this
                    error = true;
                }
            });
    
            if (error) return !error;
    
            _hub.RegisterNative(deviceToken, tags, (errorCallback) =>
            {
                if (errorCallback != null)
                {
                    /// log this
                    error = true;
                }
            });
    
            if (error) return !error;
    
            _hub.RegisterTemplate(deviceToken,
                CloudNotificationConstants.DefaultTemplateName,
                CloudNotificationConstants.DefaultTemplate,
                CloudNotificationConstants.DefaultExpiration,
                tags, (errorCallback) =>
                {
                    if (errorCallback != null)
                    {
                        /// log this
                        error = true;
                    }
                });
    
            if (error) return !error;
    
            /// private variable for our safe keeping. Not necessary
            IsRegistered = true;
            return IsRegistered;
        }
        catch(Exception e)
        {
            /// originally this caught TASK exceptions. A regular exception will do now.
            if (e is AggregateException && e.InnerException != null)
            _handler.LogException(e.InnerException);
        }
    
        return false;
    }
    
    /// We may want multiple templates, so we'll put them in a dictionary for now
    public static class CloudNotificationConstants
    {
        /// <summary>
        /// Subscription tags
        /// </summary>
        public const string DefaultSubscriptionTag = "default";
    
        /// <summary>
        /// Default notification template name
        /// </summary>
        public const string DefaultTemplateName = "defaultTemplate";
    
        public static string DefaultTemplate => Templates[DefaultTemplateName];
    
        /// <summary>
        /// The default expiration time for iOS devices
        /// </summary>
        /// <remarks> This expiration date may not actually be necessary
        public static string DefaultExpiration = DateTime.UtcNow.AddDays(365).ToString(CultureInfo.CreateSpecificCulture("en-US"));
    
        /// <summary>
        /// Default notification template
        /// </summary>
        private const string DefaultTemplateValue = "{\"aps\":{\"alert\":\"$(messageParam)\"}}";
    
        /// <summary>
        /// All notification templates
        /// </summary>
        private static Dictionary<string, string> Templates = new Dictionary<string, string>()
        {
            {DefaultTemplateName, DefaultTemplateValue}
        };
    }
    

Answers

  • ColeXColeX Member, Xamarin Team Xamurai

    Try the following code

      try
         {
               AzureNotifHub = new SBNotificationHub(HUB_LISTENSHARED_CONNSTRING, HUBNAME);
    
              // update registration with Azure Notification Hub
               await AzureNotifHub.UnregisterAllAsync(deviceToken);
    
    
               var tags = new NSSet(AppConstants.IOSSUBSCRIPTIONTAGS.ToArray());
               await AzureNotifHub.RegisterNativeAsync(deviceToken, tags);
    
               var templateExpiration = DateTime.Now.AddDays(120).ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));
                        await AzureNotifHub.RegisterTemplateAsync(deviceToken, "defaultTemplate", AppConstants.IOS_APNS_TEMPLATE_BODY, templateExpiration, tags);
          }
          catch (Exception ex)
          {
               Debug.WriteLine(ex.Message);
          }
    

    Refer https://stackoverflow.com/a/58280762/8187800.

  • gadeweevergadeweever Member ✭✭
    Accepted Answer

    Hi @ColeX,

    This doesn't seem to work either. The call to UnregisterAllAsync never completes and no exceptions are thrown. At least in the synchronous case they execute. However, we got this working after a couple days of madness.

    TL;DR:

    This works (or used to):

    • iOS 13 and all releases before
    • App built with Xcode 10
    • Certificate-based authentication in Azure Notification Hubs
    • Xamarin.Azure.NotificationHubs.iOS v1.2.5.2

    This also works (and currently still does):

    • iOS 13 and all releases before
    • App built with Xcode 11
    • Token-based authentication in Azure Notification Hubs
    • Xamarin.Azure.NotificationHubs.iOS v2.0.4

    Gotchas

    • No other configuration of resources/SDKs worked. We tried a matrix, a very large matrix, and they don't work.
    • The same token key cannot be used for both production and sandbox in the Notification Hub UI. Also, switching them breaks the other environment.

    If you're interested

    We had an iOS 13.1 device receiving notifications in December. We released a couple new version of our app, and they haven't gotten notifications since, but they only noticed after we released several newer version.

    At the time we were still on Xamarin.Azure.NotificationHubs.iOS v1.2.5.2, so we thought, "Oh something is wrong with iOS 13? just roll back to a previous version". This didn't work because they didn't roll back far enough.

    So we tried the bit conversion method below:

    byte[] token = deviceToken.ToArray();
    string registrationToken = BitConverter.ToString(token).Replace("-", "");
    

    We handed off this string to RegisterNativeAsync from V1.2.5.2 and the device was registered in notification hubs. When we tried to do a test send, it passed, but removed the registration and silently failed for iOS 13 devices only. iOS 12 devices worked with the conversion.

    After that, we scratched our heads (not literally), and updated to V2.0.4. We kept the conversion and tried again. Same issue: The registration exists until you try to send something to it.

    Then we looked at the documentation and saw we were missing the call to RegisterTemplate which was not necessary in V1.2.5.2. We still don't actually know what this really does and why it is in the documentation now but we will be investigating more later. Another migration issue. We added this. Still the same issue.

    Then we remembered that, sometime in the last month, we updated our build machines to Catalina and XCode 11. This is what actually broke everything (presumably), however it is not immediately clear why updating to a newer version of Xcode should have an impact on the validity of a registration, given that we were already doing the conversion.

    We came across this statement in the Azure documentation:

    "Apple now requires that developers identify notifications as an alert or background notifications through the new apns-push-type header in the APNS API. According to Apple's documentation: "The value of this header must accurately reflect the contents of your notification's payload. If there is a mismatch, or if the header is missing on required systems, APNs may return an error, delay the delivery of the notification, or drop it altogether."

    We thought "but this doesn't explain why the iOS 13 device isn't receiving notifications." However, maybe it affects new registrations? Additionally, the documentation states:

    "Remember that you must configure Azure Notification Hubs to use token-based authentication to set the required header; for more information, see Token-based (HTTP/2) Authentication for APNS."

    We were still using cert-based auth. We decided to switch to token based authentication and the new registrations were happy.

    I guess the issues came about from multiple solutions around mutliple different versions. We are not doing the bit conversion on either device, and everything seems to be okay.

    So far.

    @ColeX no further triage needed however, if you know anyone on the Xamarin/Hubs team, I'd love to talk with them and work on the documentation that's currently available since it has a number of mistakes, is fragmented, and is omits quite a few requirements for V1.x -> V2.x migration.

    The final code:

    public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
    {
        try
        {
            var successfulRegistration = _notificationDelegate.Register(_user.UserId, deviceToken).Result;
            if (!successfulRegistration)
            {
                /// log this
            }
        }
        catch(Exception e)
        {
            /// log this
        }
    }
    
    /// originally this used the async methods from V2.0.4.
    /// The never returned, even with .ConfigureAwait(false)
    /// The method signature retains Task<bool> even though it is not required
    public async Task<bool> Register(string userID, NSData deviceToken)
    {
        var error = false;
        try
        {
            _hub = new SBNotificationHub(
                Configuration.Configuration.NOTIFICATION_HUB_CONNECTION_STRING,
                Configuration.Configuration.NOTIFICATION_HUB_NAME);
    
            /// we add a username with our registrations.
            var tags = new NSSet(CloudNotificationConstants.DefaultSubscriptionTag, $"username:{userID}");
    
            _hub.UnregisterAll(deviceToken, (errorCallback) => {
                if (errorCallback != null)
                {
                    /// log this
                    error = true;
                }
            });
    
            if (error) return !error;
    
            _hub.RegisterNative(deviceToken, tags, (errorCallback) =>
            {
                if (errorCallback != null)
                {
                    /// log this
                    error = true;
                }
            });
    
            if (error) return !error;
    
            _hub.RegisterTemplate(deviceToken,
                CloudNotificationConstants.DefaultTemplateName,
                CloudNotificationConstants.DefaultTemplate,
                CloudNotificationConstants.DefaultExpiration,
                tags, (errorCallback) =>
                {
                    if (errorCallback != null)
                    {
                        /// log this
                        error = true;
                    }
                });
    
            if (error) return !error;
    
            /// private variable for our safe keeping. Not necessary
            IsRegistered = true;
            return IsRegistered;
        }
        catch(Exception e)
        {
            /// originally this caught TASK exceptions. A regular exception will do now.
            if (e is AggregateException && e.InnerException != null)
            _handler.LogException(e.InnerException);
        }
    
        return false;
    }
    
    /// We may want multiple templates, so we'll put them in a dictionary for now
    public static class CloudNotificationConstants
    {
        /// <summary>
        /// Subscription tags
        /// </summary>
        public const string DefaultSubscriptionTag = "default";
    
        /// <summary>
        /// Default notification template name
        /// </summary>
        public const string DefaultTemplateName = "defaultTemplate";
    
        public static string DefaultTemplate => Templates[DefaultTemplateName];
    
        /// <summary>
        /// The default expiration time for iOS devices
        /// </summary>
        /// <remarks> This expiration date may not actually be necessary
        public static string DefaultExpiration = DateTime.UtcNow.AddDays(365).ToString(CultureInfo.CreateSpecificCulture("en-US"));
    
        /// <summary>
        /// Default notification template
        /// </summary>
        private const string DefaultTemplateValue = "{\"aps\":{\"alert\":\"$(messageParam)\"}}";
    
        /// <summary>
        /// All notification templates
        /// </summary>
        private static Dictionary<string, string> Templates = new Dictionary<string, string>()
        {
            {DefaultTemplateName, DefaultTemplateValue}
        };
    }
    
  • FrankSzendzielarzFrankSzendzielarz CZMember ✭✭

    Having similar issues. TestSend from Azure Hub does not deliver to any valid tag set - always gives "Message was successfully sent, but there were no matching targets."

  • FrankSzendzielarzFrankSzendzielarz CZMember ✭✭
    edited July 24

    OK my scenario turned out to be different.

    My method body of RegisteredForRemoteNotifications also calls out to another method, like @gadeweever , but wraps that call in a Task.Run (for various unrelated reasons). Another difference is that I call the Register methods within the callback of the Unregister. In that context , the RegisterNative / RegisterTemplate method overloads that use callbacks do not work. They silently fail and do not register. The solution for me was to use the method overloads **where the error is passed as NSError. **

    eg AppDelegate.Hub.RegisterTemplate((NSData)this.pushRegistrationID, "defaultTemplate", AppConstants.APNTemplateBody, templateExpiration, tagsetLoud, out NSError errloud);

    The reason is a bit mysterious to me. Something to do with the way Xamarin translates callbacks to task/threads.

    There also seem to be implications for code implementations like the above in @gadeweever 's post: I notice that the UnregisterAll callback to set the error flag can execute after the check

    if (error) return !error;

    so there seems to be a race condition there.

  • KevinMonahan.8237KevinMonahan.8237 USMember ✭✭

    @FrankSzendzielarz I also have the register calls within the callback of Hub.UnregisterAll. I have some iphones that register ok, some finally register after reinstalling the app, and logging off and on several times. And I have other iphones that simply wont register, no matter how many times I reinstall or login..

    Did you keep the register calls within the Hub.UnregisterAll call? And then simply use the overloads, instead of the callbacks? I'm wondering if I need to move the register calls to run after the unregister call, as in gadeweever's code?

    I am unclear on how to use the NSError in the overload. Do you declare it as null, then use it as output arg? I am unfamiliar with NSError - how to you get its value after returning from call? Convert it to bool? Can you show me your code on this please?

    I have been dealing with this for weeks. Hoping your solution helps me out.

  • FrankSzendzielarzFrankSzendzielarz CZMember ✭✭
    @KevinMonahan.8237 Yes I a) used the NSError overloads b) in the callback and c) kept it on a background thread pool thread.

    I don't recommend moving the code out as I am 99% sure this is a race condition.

    I just avoid the continuation altogether and just check the error output. If you ping me again tomorrow Eve or Monday I will post my code . I am driving most the day somewhere and will need a reminder.
  • FrankSzendzielarzFrankSzendzielarz CZMember ✭✭
    edited July 25
    @KevinMonahan.8237 and one more thing, just declare the NSError as out NSError yourVar and check for non null

    I have logged a bug with the platform repo for this, I hope. In the repo for Xamarin iOS azure notification hubs. No response so far. My guess is if you are getting such non deterministic results it fits in with this threading issue.
  • gadeweevergadeweever Member ✭✭

    @FrankSzendzielarz Unfortunately we did have to move around some of the code I posted earlier. If my memory serves me right, we ended up making registration completely synchronous, without callbacks. We couldn't figure out how to make it work 100% of the time otherwise.

    @KevinMonahan.8237 We did have some shady behaviour with the callback version. You might want to see if the sync versions work as intended.

  • FrankSzendzielarzFrankSzendzielarz CZMember ✭✭
    @gadeweever Good to know. It is a bit concerning as I haven't tested on a broad set of iPhones yet. However, if results turn out to be mixed when I do, then at least I will know roughly why. It would be good to understand what this thread/callback underlying issue is precisely though.
  • KevinMonahan.8237KevinMonahan.8237 USMember ✭✭

    Thanks guys. Appreciate the input! @FrankSzendzielarz I have my code set to run on main thread, after login. (I get my TAGs from the database, during the login process). I am on the main thread, because of what someone said here:
    https://forums.xamarin.com/discussion/162951/xamarin-forms-ios-droid-guide-for-azure-notification-hub-that-actually-works-as-of-july-2019

    You say you kept in on the background thread. Should i do that as well? The below code is working for my test iphone 7.

    /*
    * just a quick tip...on IOS side when you register your hub, it should be done on mainthread (usualy directly in the appdelegate). 
    * Doesn't work otherwise (doesn't seems to work in an async method). So if you're planning to be async (like registering after a login 
    * process to have a unique push token for every users) don't forget that. 
    * It took me a while to understand why it worked when registering where placed in the AppDelegate, and not working when registered 
    * in another class called asynchronously.
    */
    

    My code:

    //use DependencyService to call andoid/iOS code that registers with azure notificationhub.
    switch (Device.RuntimePlatform)
    {
        case Device.iOS:
    
            Device.BeginInvokeOnMainThread(async () =>
            {
                await Task.Run(() =>
                {
                    DependencyService.Get<SixTen.Interfaces.IRegisterTags>().RegTags(SixTenMemberApp.App.IosToken);
                });
    
                //DependencyService.Get<SixTen.Interfaces.IRegisterTags>().RegTags(SixTenMemberApp.App.IosToken);
            });
            break;
        case Device.Android:
            await Task.Run(() =>
            {
                DependencyService.Get<SixTen.Interfaces.IRegisterTags>().RegTags(SixTenMemberApp.App.AndroidToken);
            });
            break;
    }
    

    And my RegTags code in ios project:

    NSSet tags = null;
    NSData deviceToken = (NSData)PassedToken;
    App.SendApiDebugLog("iOS RegisterTags", "RegTags", "token", deviceToken.ToString());
    
    string storage_TildeDelimitedUserTags = GetSecureStorage("TildeDelimitedUserTags");
    if (!string.IsNullOrEmpty(storage_TildeDelimitedUserTags))
    {
        string[] spl_TildeDelimitedUserTags = storage_TildeDelimitedUserTags.Split('~');
        tags = new NSSet(spl_TildeDelimitedUserTags);
    }
    App.SendApiDebugLog("iOS RegisterTags", "RegTags", "storage_TildeDelimitedUserTags", storage_TildeDelimitedUserTags);
    
    SBNotificationHub Hub = new SBNotificationHub(AppConstants.ListenConnectionString, AppConstants.NotificationHubName);
    Hub.UnregisterAll(deviceToken, (error) =>
    {
        if (error != null)
        {
            App.UnregisterAll = "Unable to call unregister: " + error;
            App.WriteStartupErrorsToDb();
            return;
        }
        else
        {
            App.UnregisterAll = "UnregisterAll Success!";
        }
    
        if (tags != null)
        {
            NSError ns_error = null;
    
            Hub.RegisterNative(deviceToken, tags, out ns_error);
            if (ns_error != null)
            {
                App.RegisterNative = "RegisterNativeAsync error: " + ns_error;
            }
            else
            {
                App.RegisterNative = "RegisterNative Success!";
            }
    
            ns_error = null;
            var templateExpiration = DateTime.Now.AddDays(365).ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));
            Hub.RegisterTemplate(deviceToken, "defaultTemplate", AppConstants.APNTemplateBody, templateExpiration, tags, out ns_error);
            if (ns_error != null)
            {
                App.RegisterTemplateAsync = "RegisterTemplateAsync error: " + ns_error;
            }
            else
            {
                App.RegisterTemplateAsync = "RegisterTemplateAsync Success!";
            }
            tags.Dispose();
        }
    
        //log App variables (App.UnregisterAll,App.RegisterNative, etc.) to the database for users with logging turned on.
        App.WriteStartupErrorsToDb();
    
    });
    

    I wont know until I release if this is going to work for the problem iphones, hoping for the best.

  • KevinMonahan.8237KevinMonahan.8237 USMember ✭✭

    @gadeweever and @FrankSzendzielarz

    Maybe you guys can answer a question for me - please see my post here:

    http:/https://forums.xamarin.com/discussion/183866/azure-notification-hub-native-vs-template-registration/p1?new=1/

    You two seem to be in the same place as me on notifications - I would appreciate any info you have. Thanks!

  • FrankSzendzielarzFrankSzendzielarz CZMember ✭✭

    @KevinMonahan.8237 I was going to post my code, but in essence you have exactly the same thing as me. It works for me using iPhone 5.
    However! Note that in your code you have the Device.BeginInvokeOnMainThread executing a Task.Run, which I would probably guess is redundant. You are asking the main thread to run a task on the threadpool. Regardless, it's the same as what I am doing: I am using Task.Run in both ios and android cases because I don't think the call out to the Azure web api should be done on the main thread.
    In this situation the RegisterTemplate/RegisterNative calls do not work using the callback overload, but the NSError overloads you chose above do.

  • All, solution to similar problems here https://github.com/Azure/azure-notificationhubs-ios/issues/95

    In short, don't use SBNotificationHub use MSNotificationHub.

Sign In or Register to comment.