I've created a sample app for testing push notifications on iOS. I'm running Visual Studio 2019 on a PC, which is connected over a local network to a MAC. An iPhone is connected to the MAC via lightning cable. As the title suggests, ReceivedRemoteNotification method is never called when I Test Send from Azure. Azure informs me that the test message was sent successfully.
I've followed this guide multiple times and rigorously:
RegisteredForRemoteNotifications is called so it appears that the app successfully registers for push notifications. I also get the permission request on the physical device, which I accept. However I have noticed that when I hover over 'Hub' inside this method, under the class handle it gives an error:
"Unable to cast object of type 'Mono.Debugger.Soft.PointerValue' to type 'Mono.Debugger.Soft.PrimitiveValue'."
however I'm not sure if this is actually related at all to my problem. I can't find anything online aside from this link which only suggests that a workaround to that error is to run in release as opposed to debug.
Sample code straight from the microsoft guide I linked above:
namespace PushNotifTestApp.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
private SBNotificationHub Hub { get; set; }
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound,
(granted, error) => InvokeOnMainThread(UIApplication.SharedApplication.RegisterForRemoteNotifications));
}
else if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
{
var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
new NSSet());
UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
else
{
UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
}
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
Hub = new SBNotificationHub(Constants.ListenConnectionString, Constants.NotificationHubName);
Hub.UnregisterAll(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.RegisterNative(deviceToken, tags, (errorCallback) => {
if (errorCallback != null)
System.Diagnostics.Debug.WriteLine("RegisterNative error: " + errorCallback.ToString());
});
});
}
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
ProcessNotification(userInfo, false);
}
void ProcessNotification(NSDictionary options, bool fromFinishedLaunching)
{
// Check to see if the dictionary has the aps key. This is the notification payload you would have sent
if (null != options && options.ContainsKey(new NSString("aps")))
{
//Get the aps dictionary
NSDictionary aps = options.ObjectForKey(new NSString("aps")) as NSDictionary;
string alert = string.Empty;
//Extract the alert text
// NOTE: If you're using the simple alert by just specifying
// " aps:{alert:"alert msg here"} ", this will work fine.
// But if you're using a complex alert with Localization keys, etc.,
// your "alert" object from the aps dictionary will be another NSDictionary.
// Basically the JSON gets dumped right into a NSDictionary,
// so keep that in mind.
if (aps.ContainsKey(new NSString("alert")))
alert = (aps[new NSString("alert")] as NSString).ToString();
//If this came from the ReceivedRemoteNotification while the app was running,
// we of course need to manually process things like the sound, badge, and alert.
if (!fromFinishedLaunching)
{
//Manually show an alert
if (!string.IsNullOrEmpty(alert))
{
var myAlert = UIAlertController.Create("Notification", alert, UIAlertControllerStyle.Alert);
myAlert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(myAlert, true, null);
}
}
}
}
}
}