Forum Xamarin.iOS
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Cannot register in Azure NotificationHub on iOS, no callbacks

SergTomcatSergTomcat Member ✭✭

I'm trying to set up push notifications (using these guides). Android went fine, but iOS...

No matter what I do, I do not receive any callbacks from RegisterNative / RegisterTemplate methods of SBNotificationHub, and no registrations appear in the hub.

I refered to similar questions (like this and that), but nothing helped.

My code (pretty straightforward):

public static void SubscribeToAzure(NSData deviceToken, string[] subscriptionTags = null, bool bUnsubscribe = false)
{
    try
    {
        var Hub = new SBNotificationHub(AppConstants.ListenConnectionString, AppConstants.NotificationHubName);

        Logger.WriteLine($"Unsubscribing from AzureHub [{deviceToken}]....");

        Hub.UnregisterAll(deviceToken, (error) =>
        {
            if (error != null)
            {
                Logger.WriteLine($"SubscribeToAzure: Unable to call unregister, {error}");
                return;
            }
            RuntimeInfo.AzureSubscribed = false;

            if (bUnsubscribe)
                return;

            Logger.WriteLine($"Register native in AzureHub [{deviceToken}]....");

            var tags = subscriptionTags != null ? new NSSet(subscriptionTags.ToArray()) : new NSSet("default");
            Hub.RegisterNative(deviceToken, tags, errorCallback =>
            {
                // !!! never got here !!!

                if (errorCallback != null)
                    Logger.WriteLine($"RegisterNative error: {errorCallback}");
                else
                    Logger.WriteLine($"RegisterNative OK");
            });

            Logger.WriteLine("Register template in AzureHub....");

            var templateExpiration = DateTime.Now.AddDays(120).ToString(System.Globalization.CultureInfo.CreateSpecificCulture("en-US"));

            Hub.RegisterTemplate(deviceToken, "defaultTemplate", AppConstants.APNTemplateBody, templateExpiration, tags, errorCallback =>
            {
                // !!! never got here !!!

                if (errorCallback != null)
                {
                    Logger.WriteLine($"RegisterTemplateAsync error: {errorCallback}");
                }
                else
                {
                    Logger.WriteLine("Subscribed to Azure successfully.");
                    RuntimeInfo.AzureSubscribed = true;
                }
            });

            Logger.WriteLine("Registrations passed....");
        });
    }
    catch(Exception e)
    {
        Logger.WriteLine($"SubscribeToAzure: Whole deal failed, {e.Message}");
    }
}

Always get this log messages (no callbacks called):

[22.10.2020 18:13:43]: Unsubscribing from AzureHub [{length = 32, bytes = 0x342c9bc5 d75ffb0b d68078d0 47e94320 ... e08989c9 66a13a37 }]....
[22.10.2020 18:13:44]: Register native in AzureHub [{length = 32, bytes = 0x342c9bc5 d75ffb0b d68078d0 47e94320 ... e08989c9 66a13a37 }]....
[22.10.2020 18:13:44]: Register template in AzureHub....
[22.10.2020 18:13:44]: Registrations passed....

And no iOS registrations in the hub. And no errors anywhere.

I tried both certificate and token authentication modes, with no luck.

I have double-, triple- and quadruple-checked all certificates, statuses, keys, ids, etc.

Using iOS SDK 14.0, iPhone X iOS 14.0.1, Xamarin Forms 4.8.0.1560, Xamarin.Azure.NotificationHubs.iOS 3.1.0.

Hope someone could direct me to, at least, getting error from SBNotificationHub.

Thank you in advance.

Answers

  • ColeXColeX Member, Xamarin Team Xamurai

    Have you tried to use MSNotificationHub instead of SBNotificationHub ?

    SBNotificationHub is still available but it is discouraged .


    Refer to

    https://github.com/Azure/azure-notificationhubs-ios/issues/95
    https://github.com/azure/azure-notificationhubs-xamarin#getting-started-with-xamarin-for-apple

  • SergTomcatSergTomcat Member ✭✭

    @ColeX said:
    Have you tried to use MSNotificationHub instead of SBNotificationHub ?

    SBNotificationHub is still available but it is discouraged .


    Refer to

    https://github.com/Azure/azure-notificationhubs-ios/issues/95
    https://github.com/azure/azure-notificationhubs-xamarin#getting-started-with-xamarin-for-apple

    Tried it with MSNotificationHub, still have the same result: no response if something went wrong or not. And no registrations in the hub.

    public static void SubscribeToAzure(NSData deviceToken, string[] subscriptionTags = null, bool bUnsubscribe = false)
    {
        RuntimeInfo.AzureSubscribed = false;
    
        if (bUnsubscribe)
        {
            // ??
        }
        else
        {
            try
            {
    
                Logger.WriteLine("Subscribing to Azure Hub....");
    
                MSNotificationHub.Start(AppConstants.ListenConnectionString, AppConstants.NotificationHubName);
    
                MSNotificationHub.SetDelegate(new NotificationDelegate());
    
                MSNotificationHub.SetLifecycleDelegate(new InstallationLifecycleDelegate());
    
                MSNotificationHub.ClearTags();
    
                if (subscriptionTags != null)
                    foreach (string tag in subscriptionTags)
                    {
                        MSNotificationHub.AddTag(tag);
                    }
    
                var template = new MSInstallationTemplate();
                template.Body = AppConstants.APNTemplateBody;
    
                if (subscriptionTags != null)
                    foreach (string tag in subscriptionTags)
                    {
                        template.AddTag(tag);
                    }
    
                MSNotificationHub.SetTemplate(template, key: "defaultTemplate");
    
    
                Logger.WriteLine($"SubscribeToAzure: done subscribing routine");
            }
            catch (Exception e)
            {
                Logger.WriteLine($"SubscribeToAzure: Whole deal failed, {e.Message}");
            }
        }
    }
    public class InstallationLifecycleDelegate : MSInstallationLifecycleDelegate
    {
        public override void DidFailToSaveInstallation(MSNotificationHub notificationHub, MSInstallation installation, NSError error)
        {
            Logger.WriteLine($"Subscribing to Azure failed with exception: {error.LocalizedDescription}");
        }
    
        public override void DidSaveInstallation(MSNotificationHub notificationHub, MSInstallation installation)
        {
            RuntimeInfo.AzureSubscribed = true;
            Logger.WriteLine($"Subscribed to Azure successfully with Installation ID: {installation.InstallationId}");
        }
    }
    public class NotificationDelegate : MSNotificationHubDelegate
    {
        public override void DidReceivePushNotification(MSNotificationHub notificationHub, MSNotificationHubMessage message)
        {
            NSDictionary userInfo = message.UserInfo;
            if (UIApplication.SharedApplication.ApplicationState == UIApplicationState.Background)
            {
                Logger.WriteLine($"Message received in the background with title {message.Title} and body {message.Body}");
                ProcessNotification(userInfo, true);
            }
            else
            {
                Logger.WriteLine($"Message received in the foreground with title {message.Title} and body {message.Body}");
                ProcessNotification(userInfo, true);
            }
        }
    }
    

    Log only shows that all parts of code were passed:

    [23.10.2020 18:34:33]: Subscribing to Azure Hub....
    [23.10.2020 18:34:33]: SubscribeToAzure: done subscribing routine

    Kinda stuck here...

  • ColeXColeX Member, Xamarin Team Xamurai
    edited October 27

    Please raise the issue on github for better support: https://github.com/Azure/azure-notificationhubs-ios/issues?q=is:open+is:issue .

  • SergTomcatSergTomcat Member ✭✭

    After 5 days I finally figured out about callbacks. If processing slips from main thread, for some reason iOS blocks connections, and Xamarin.Azure.NotificationHubs.iOS doesn't say anything. Running it all forcibly in main thread seems to make it all move.

    Anyway, it still doesn't work.

    The first approach with SBNotificationHub fail to register template. Code above do RegisterNative and I get native entry in notification hub. But RegisterTemplate return 'Bad Request'.

    [28.10.2020 15:26:10]: RegisterTemplateAsync error: URLRequest failed for { URL: https://webtutormobile.servicebus.windows.net//Registrations/8635975298502840400-8846379580641729326-3?api-version=2013-04 } with status code: bad request

    Second approach with MSNotificatoinHub fail to obtain NSDictionary from MSNotificationHubMessage.userInfo getter, and breaks on this line:

    public override void DidReceivePushNotification(MSNotificationHub notificationHub, MSNotificationHubMessage message)
    {
            var userInfo = message.UserInfo; // MSNotificationHubMessage.UserInfo has type NSDictionary<NSString, NSString>
    
    
    

    with exception:

    [28.10.2020 16:22:58]: Received azure notification error: Unable to cast object of type 'Foundation.NSDictionary' to type 'Foundation.NSDictionary`2[[Foundation.NSString, Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065],[Foundation.NSString, Xamarin.iOS, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065]]'

    I would really appreciate if you could help me beat it....

  • ColeXColeX Member, Xamarin Team Xamurai
    edited October 29

    For the second approach change your code as below

    NSDictionary<NSString, NSString> userInfo = message.UserInfo;
       NSString value = userInfo[new NSString("key")];
    
  • SergTomcatSergTomcat Member ✭✭

    @ColeX said:
    For the second approach change your code as below

    NSDictionary<NSString, NSString> userInfo = message.UserInfo;
    NSString value = userInfo[new NSString("key")];

    As I said earlier, it's not working inside getter, it is casted to NSDictionary<NSString, NSString>, but actual type is NSDictionary.

    [BindingImpl(BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
            public virtual NSDictionary<NSString, NSString> UserInfo
            {
                [Export("userInfo")]
                get
                {
                    if (base.IsDirectBinding)
                    {
                        return Runtime.GetNSObject<NSDictionary<NSString, NSString>>(ApiDefinition.Messaging.IntPtr_objc_msgSend(base.Handle, Selector.GetHandle("userInfo")));
                    }
    
                    return Runtime.GetNSObject<NSDictionary<NSString, NSString>>(ApiDefinition.Messaging.IntPtr_objc_msgSendSuper(base.SuperHandle, Selector.GetHandle("userInfo")));
                }
            }
    
    
Sign In or Register to comment.