maui
maui copied to clipboard
MAUI .net7 / .net8 ios push notifications not received in DidReceiveRemoteNotification
Description
Can not receive push notification in maui application on iOS when the application is running (in foreground). Looks like everything works except receiving push notifications in app. I successfully register for notifications and get push token.
public class AppDelegate : MauiUIApplicationDelegate, IUNUserNotificationCenterDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
RegisterForRemoteNotifications(app);
return base.FinishedLaunching(app, options);
}
private void RegisterForRemoteNotifications(UIApplication app)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// iOS >= 10
UNUserNotificationCenter.Current.RequestAuthorization(
UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound,
(granted, error) =>
{
if (error != null) {}// log error.DebugDescription
});
UNUserNotificationCenter.Current.Delegate = this; // implemented in AppDelegate methods: WillPresentNotification and DidReceiveNotificationResponse from IUNUserNotificationCenterDelegate
}
else
{
var settings = UIUserNotificationSettings.GetSettingsForTypes(
UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
app.RegisterForRemoteNotifications();
}
[Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
public void DidReceiveRemoteNotification(UIKit.UIApplication application, NSDictionary userInfo, Action<UIKit.UIBackgroundFetchResult> completionHandler)
{
...
completionHandler(UIBackgroundFetchResult.NoData);
}
[Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
public void RegisteredForRemoteNotifications(UIKit.UIApplication application, NSData deviceToken)
{
var deviceTokenHex = ByteArrayHelper.BytesToHex(deviceToken?.ToArray());
...
}
[Export("application:didFailToRegisterForRemoteNotificationsWithError:")]
public void FailedToRegisterForRemoteNotifications(UIKit.UIApplication application, NSError error)
{
// error.DebugDescription
...
}
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
// notification?.Request?.Content?.UserInfo
...
}
// user clicked at presented notification
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
...
}
...
}
Steps to Reproduce
- Create new project.
- Setup push notifications on the apple side (certificates etc)
- Implement notifications like in description In app:
- Register for notifications
- Get push token
- Send notification to device when app is in background - works fine!
- Send notification to device when app is in foreground - nothing happens
Link to public reproduction project repository
No response
Version with bug
7.0.96
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
Unknown/Other
Affected platforms
iOS
Affected platform versions
iOS 17.0.3
Did you find any workaround?
no
Relevant log output
No response
I'm experiencing a similar issue and was wondering if the development team had any input that could help?
Can you try doing this, this is what fixed the issue for me Issue 194 - Plugin.Firebase.CloudMessaging
I don't use firebase. I don't quite understand, is it possible to "catch" an incoming push notification if you subscribe to "iOS.WillFinishLaunching" ? Or it works with firebase plugin only ?
Please ignore the above comment, for some reason I assumed that you were using the plugin.
As to your issue, in iOS when the application is in the foreground, you'll need to handle the notification because iOS will not automatically display the notification to the user. The easiest way would be to create a local notification.
@aleks42 Any news here? Did you found a solution? I have same problem. Notification in background is working, but not in foreground. We also do not use firebase. We use Azure Notification Hub and Microsoft do not provide a plugin.
To tell the truth, I've come to the conclusion that this feature doesn't work. In my case, there is a relatively short time when a push notification can appear in the foreground. I just call the backend several times on a timer and show a notification if new ones appear. I haven't checked how it works in .net 8 yet.
Did anybody get didReceiveRemoteNotification to work in MAUI .Net8? I can't get the method to be triggered in AppDelegate, no matter what I try. WillPresentNotification() is triggered when the app is in foreground, but I also need to handle silent notifications while the app is backgrounded.
Did anybody get didReceiveRemoteNotification to work in MAUI .Net8? I can't get the method to be triggered in AppDelegate, no matter what I try. WillPresentNotification() is triggered when the app is in foreground, but I also need to handle silent notifications while the app is backgrounded.
I have the same issue. :( Any solution for .net 8?
Did anybody get didReceiveRemoteNotification to work in MAUI .Net8? I can't get the method to be triggered in AppDelegate, no matter what I try. WillPresentNotification() is triggered when the app is in foreground, but I also need to handle silent notifications while the app is backgrounded.
It doesn't even work for me in the foreground, did you do anything special for that? thanks
Same for me, i try using 2 plugin, Plugin.Firebase.CloudMessaging and with Plugin.FirebasePushNotification but no one works, even if all the code works and i am able to receive the FCM token
same issue, any solution?
I've ended up implementing a workaround. Instead of relying on didReceiveRemoteNotification to receive data payload I've implemented am API service that I query on application activation to retrieve whatever data the application needs.
This means that when the user starts the app or when he taps on a visible notification that triggers the app to start, the application retrieves the data it needs...
Any update on this issue?
I've also faced with the same issue. Any updates on it?
Any updates on this? Did anyone manage to find a workaround that doesn't imply any backend changes? The project that I am working on really needs background (silent) notifications because the notification needs to be displayed by the app in the user's language, information that is not available on the backend.
Do you know why my program crashes when I get to the line in debug UNUserNotificationCenter.Current.Delegate = this;
It seems like I implemented everything, but it doesn't throw any exceptions, it just doesn't work anymore
well, I found out that in debug mode completely removing the entilements.pList file the debug works again here to run on real devices in debug, but to publish in test it is necessary to add and generate the package, it seems that even the configuration determined only in realese in cs is no use, just the fact of having the file in the iOS folder affects in debug, and it doesn't allow, I managed to get pushes with app closed and in the background the notifications, and apparently pass through didReceiveNotificationResponse and didReceiveIncomingPushWithPayload in release, but in debug nothing.. I can leave the app in the background that only in payload works in normal notifications no.. in the case in didReceiveNotificationResponse debug mode still doesn't work, only in realese, but for me what made debug work in real device was to remove entilements file from the project even though it is not set in cs.proj
work for me in realese mode, but not in debug mode (does not work and does not run device if there is an entilements file in the iOS folder)
public class UserNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public async override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler){
}
}
Working for my in debug mode and realese mode from voip
[Register("PushRegistryDelegate")]
public class PushRegistryDelegate : PKPushRegistryDelegate
{
[Export("pushRegistry:didReceiveIncomingPushWithPayload:forType:withCompletionHandler:")]
public override void DidReceiveIncomingPush(PKPushRegistry registry, PKPushPayload payload, string type, Action completionHandler)
{
}
}
in AppDelegate....
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
instance = this;
UNUserNotificationCenter.Current.Delegate = new UserNotificationCenterDelegate();
var voipRegistry = new PKPushRegistry(DispatchQueue.MainQueue);
voipRegistry.Delegate = new PushRegistryDelegate();
voipRegistry.DesiredPushTypes = new NSSet(new string[] { PKPushType.Voip });
return base.FinishedLaunching(application, launchOptions);
}
Here's what I've got goin on in iOS and it works great. Note I am using FCM so if you're not just ignore things that begin with Messaging. Currently running .NET 8 for iOS and Android. Hope this helps somebody.
Another note: WillPresentNotification in the NotificationDelegate is where I am handling (to not show) notifications in the foreground.
Here are the packages being used.
<ItemGroup> <!-- This is used for both iOS and Android -->
<PackageReference Include="Xamarin.Build.Download" Version="0.11.4" />
</ItemGroup>
<!-- Was getting a lot of Android build errors but this combination of nugets seems to be the fix -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0-android'">
<PackageReference Include="Xamarin.AndroidX.Activity">
<Version>1.9.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Activity.Ktx">
<Version>1.9.1.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Collection">
<Version>1.4.2.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Collection.Ktx">
<Version>1.4.2.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4">
<Version>1.0.0.28</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData">
<Version>2.8.4.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Firebase.Messaging">
<Version>124.0.0.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Google.Dagger">
<Version>2.52.0</Version>
</PackageReference>
<PackageReference Include="Xamarin.GooglePlayServices.Base">
<Version>118.5.0.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0-ios'">
<PackageReference Include="Xamarin.Firebase.iOS.CloudMessaging" Version="8.10.0.3" />
</ItemGroup>
Global usings in MauiProgram.cs
#if ANDROID
global using Firebase.Messaging;
global using AndroidX.AppCompat.Widget;
global using Android.App;
global using Android.Content;
#elif IOS
global using UIKit;
global using Firebase.CloudMessaging;
global using Foundation;
global using UserNotifications;
#endif
AppDelegate.cs
[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate, IMessagingDelegate
{
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
if (Messaging.SharedInstance is null)
{
Firebase.Core.App.Configure();
}
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// For iOS 10 display notification (sent via APNS)
/* For devices running iOS 10 and above, you must assign your delegate object
* to the UNUserNotificationCenter object to receive display notifications,
* and the Messaging object to receive data messages, before your app
* finishes launching. For example, in an iOS app, you must assign it
* in the WillFinishLaunching or FinishedLaunching method.
*/
Messaging.SharedInstance.Delegate = this;
Messaging.SharedInstance.AutoInitEnabled = true;
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) =>
{
if (error is not null)
{
LogError(error.LocalizedDescription);
}
});
UNUserNotificationCenter.Current.Delegate = new UserNotificationCenterDelegate();
}
else
{
// iOS 9 or before
UIUserNotificationType allNotificationTypes = UIUserNotificationType.Alert;
UIUserNotificationSettings settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
return base.FinishedLaunching(application, launchOptions);
}
/*
If you want to get notifications while the app is closed . Try messing with these .
[Foundation.Export("application:didReceiveRemoteNotification:")]
public void ReceivedRemoteNotification(UIKit.UIApplication application, Foundation.NSDictionary userInfo)
{
}
[Foundation.Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
public async void DidReceiveRemoteNotification(UIKit.UIApplication application, Foundation.NSDictionary userInfo, Action<UIKit.UIBackgroundFetchResult> completionHandler)
{
}
*/
// This is FCM specific for firebase tokens
[Export("messaging:didReceiveRegistrationToken:")]
public void DidReceiveRegistrationToken(Messaging message, string regToken)
{
}
}
UserNotificationCenterDelegate.cs
public class UserNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
// For some reason I found that calling base.DidReceiveNotificationResponse(...) and base.WillPresentNotification(...) were causing issues so I removed them.
public async override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
}
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
if (AppIsInForeground != true)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(14, 2))
{
completionHandler(UNNotificationPresentationOptions.List | UNNotificationPresentationOptions.Banner | UNNotificationPresentationOptions.Badge | UNNotificationPresentationOptions.Sound);
}
else if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
completionHandler(UNNotificationPresentationOptions.Badge | UNNotificationPresentationOptions.Sound);
}
else
{
// Do our notifications need more configuration to work below 10?
completionHandler(UNNotificationPresentationOptions.Alert);
}
}
}
}
✌
What's is AppIsInForeground var?