Search code examples
xamarin.iosapple-push-notificationsmauiunusernotificationcentersilentpush

.Net Maui iOS app with Silent Push Notifications ReceivedRemoteNotification or DidReceiveRemoteNotification never gets called


I'm using Plugin.Firebase and my own APN Server. I can send a message with an alert payload. This works just fine. If I send a message with a content-available payload, nothing happens.

I'm using the current version of the .Net 7 release. My target is iOS 16. My test device is an iPhone 12 running iOS 15.7.

Here are some key components of my AppDelegate.

This has been added to FinishedLaunching.

var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
        UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) =>
        {
            //this.Log($"RequestAuthorization: {granted}" + (error != null ? $" with error: {error.LocalizedDescription}" : string.Empty));

            if (granted && error == null)
            {
                this.InvokeOnMainThread(() =>
                {
                    UIApplication.SharedApplication.RegisterForRemoteNotifications();
                    //this.InitFirebase();

                    UNUserNotificationCenter.Current.Delegate = this;
                });
            }
        }); 

Here is DidReceiveRemoteNotification.

https://learn.microsoft.com/en-us/dotnet/api/uikit.uiapplicationdelegate.didreceiveremotenotification?view=xamarin-ios-sdk-12

//App is in the foreground
    [Foundation.Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
    public void DidReceiveRemoteNotification(UIKit.UIApplication application, Foundation.NSDictionary userInfo, Action<UIKit.UIBackgroundFetchResult> completionHandler)
    {
        SentrySdk.CaptureMessage("DidReceiveNotificationResponse = " + "yes");
        
        ProcessNotification(userInfo, false);

        completionHandler(UIBackgroundFetchResult.NewData);

    }

Here is ReceivedRemoteNotification.

https://learn.microsoft.com/en-us/dotnet/api/uikit.uiapplicationdelegate.receivedremotenotification?view=xamarin-ios-sdk-12

//App is in the background
    [Foundation.Export("application:didReceiveRemoteNotification:")]
    public void ReceivedRemoteNotification(UIKit.UIApplication application, Foundation.NSDictionary userInfo)
    {
        SentrySdk.CaptureMessage("ReceivedRemoteNotification = " + "yes");

        ProcessNotification(userInfo, false);

    }

Here is the APS payload.

public AppleNotificationSilent() 
        {
            //Id = id;

            Aps = new ApsPayload
            {
                //AlertBody = new ApsPayload.Alert
                //{
                //    Title = title,
                //    SubTitle = subtitle,
                //    Body = message
                //},

                //Alert = "",
                ContentAvailable = 1,
                //PushType = "background",
                //Priority = 5,
                CustomKey = "GetData" //THIS WORKS
            };
            //CustomKey = "GetData";
        }

Here is what ContentAvailable looks like.

[JsonProperty("content-available")]
            public int ContentAvailable { get; set; }

Finally, I've changed the following headers for silent push.

apns-push-type = "background"
apns-priority = 5

I've noticed that the overrides for DidReceiveRemoteNotification and ReceivedRemoteNotification aren't found. This was supposed to added to the .Net 7 Maui release. I've also noticed that the decoration Export for both methods is the same except for fetchCompletionHandler in DidReceiveRemoteNotification.

Here is some additional information on how this is supposed to work.

https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/ios-backgrounding-techniques/updating-an-application-in-the-background

https://learn.microsoft.com/en-us/xamarin/ios/platform/user-notifications/enhanced-user-notifications?source=recommendations&tabs=macos

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app

Does anyone know why this isn't working? Thanks!

BEGIN UPDATE 1

A silent push notification will call this method when the app is open and in the foreground.

// App is in the foreground
    [Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
    public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
    {
        SentrySdk.CaptureMessage("DidReceiveNotificationResponse = " + "yes");

        ShowLocalNotification();

        //this.Log($"{nameof(DidReceiveNotificationResponse)}: " + response.Notification.Request.Content.UserInfo);
        completionHandler();
    }

END UPDATE 1

BEGIN UPDATE 2

After adding the fix found in the answer, all silent push notifications are now handled by DidReceiveRemoteNotification.

END UPDATE 2


Solution

  • Make sure you have this in your csprog file. I'm now able to receive silent push notifications when the app is open / being used, open / in the background, and while not running at all.

    https://github.com/dotnet/maui/issues/6259#issuecomment-1109359755

    Here is what mine looks like.

    <PropertyGroup>
        <MtouchExtraArgs>--optimize:-static-block-to-delegate-lookup</MtouchExtraArgs>
        <CodesignKey>iPhone Developer</CodesignKey>
    </PropertyGroup>
    

    The weird part about this is that all the silent push messages are being handled by DidReceiveRemoteNotification.