[Bug] iOS not receiving notification
I have posted a response to an open discussion here explaining that we are not receiving notification on iOS. We transferred to this plugin from Shiny.NET making the changes outlined in your guides. Overall, it went smoothly, and Android works great.
Steps to Reproduce
- We have added all the references and hooks outlined in the setup guides
- After deployment of Android and iOS, Android works as expected but iOS fails to receive any notifications
- On iOS, we do receive a request for permission and a token is generated (we persist this to the DB)
- When using the Firebase notification test console, we receive the Android notification, but nothing on iOS
Expected Behavior
- iOS receives a notification as it did with Shiny.NET
Actual Behavior
- iOS does not receive the notification
Basic Information
- Our iOS devices are running variations of iOS version 18.x, the same as they were with Shiny.NET
- We are using .net 8.x LTS
Thanks for reporting this.
- Did you compare your solution (csproj, MauiProgram, etc) witz the sample app in this repository?
- Did you clean & rebuild before you run the apps?
- Did you observe the log output for warnings/errors from any „firebase“ service?
- Did you compare your solution (csproj, MauiProgram, etc) witz the sample app in this repository?
Yes, all setup code and config matches (platform specific, CSPROJ, and events).
- Did you clean & rebuild before you run the apps?
Not only did a clean/rebuild, but also had to rebuild my nuget cache due to conflicts with the Shiny.NET package. All build clean and runs locally on both iOS and Android. Just not getting notifications in iOS, but Android is. Never have been able to get iOS push working with Hot Restart... think I read somewhere that will not work, so I need to release build and deploy each time to test.
- Did you observe the log output for warnings/errors from any „firebase“ service?
I did not see anything in the logs indicating a firebase issue coming across. Would there be additional events that might be logged that would indicate a problem?
Thank you for helping on this...
I don't know much about Hot Reload - other than it mostly doesn't work properly. In the log output you should at least see the debug message "ConfigurePlatform" logged by "FirebasePushNotificationManager". If this message doesn't appear, you probably have not configured logging properly or the log category is set 'too high' (e.g. info instead of debug).
Just to exclude firebase console configuration issues: You configured the correct P8 file in firebase console? When you send notification messages via Postman (or similar), do you get a success response? (I think you get better control of the messages when you use Postman instead of the build-in firebase test message sender).
What if you build a minimal reproduction app, similar to your production app. It's pretty difficult to help here. What I can guarantee is that the code in this library works (because we're using it in production apps - and many others do so too). The question ist, what is the missing piece and/or how can we improve the code/docs of this library to not have such situations again).
Can you compare the AppDelegate.cs of the sample app in this repo and you app?
Can you compare the AppDelegate.cs of the sample app in this repo and you app?
I compared, the only difference is the two exception methods... I excluded those.
In the log output you should at least see the debug message "ConfigurePlatform" logged by "FirebasePushNotificationManager". If this message doesn't appear, you probably have not configured logging properly or the log category is set 'too high' (e.g. info instead of debug).
In the log, we noticed a couple of things that might be useful. number 1, we are not seeing the "ConfigurePlatform" message at all. But we do see the one in the image below:
In addition to that, we see this one too:
And this is the only other one with Firebase in the text:
Those images are in the order they appeared in the log. No other errors or anything else that stood out.
Thanks again!
"ConfigurePlatform" is written to ILogger (Microsoft.Extensions.Logging) when IFirebasePushNotifications.Current is initialized. The error logged by Firebase SDK indicates that something is wrong with the GoogleService-Info.plist (that at least what I guess). Either it's not present or it's not configured in csproj or not properly linked in csproj (Link attribute).
If you can provide a reproduction app I might be able to troubleshoot the problem.
I have the same PLIST as I did with Shiny.NET when it was working (have not moved or changed any Firebase settings or files). It is referenced in CSPROJ like below:
<ItemGroup Condition="$(TargetFramework.Contains('-ios'))">
<BundleResource Include="Platforms\iOS\GoogleService-Info.plist" Link="GoogleService-Info.plist" />
</ItemGroup>
I will work with my team to create something for you ASAP.
Thanks!
I'm sorry for the extra effort. I'm sure we'll figure out the problem. It's probably something very stupid (as always) :) One more thing: Are you using the iOS simulator or a physical iOS device? (I experienced problems with the simulator concerning push notifications in the past).
I'm sorry for the extra effort. I'm sure we'll figure out the problem. It's probably something very stupid (as always) :)
I wish this wasn't true! But I imagine you are 100% correct.
One more thing: Are you using the iOS simulator or a physical iOS device? (I experienced problems with the simulator concerning push notifications in the past).
We have never been able to get notifications to work on a simulator -or- device connected to Windows with Hot Restart. I believe I read somewhere that Hot Restart is not supported for any notifications on a physical device. Unfortunately, the only way we have been able to test this is to go through our entire pipeline release process and download a signed store version to a physical device. I wish it were easier like with Android... and "as always", the iOS issues always seem the more mysterious ones... at least with MAUI!
If you can provide a reproduction app I might be able to troubleshoot the problem.
I apologize this took so long, was attempting other things first. No luck getting it to work in the full app, so attached is a skeleton app using the exact same process we are in the full app (for the most part). We were able to reproduce the same result where Android works fine, but iOS does not receive the message. I have included shells of the Google Firebase plist and json in the locations we have them in our main app as well.
Please let me know if this helps to determine what we are missing.
Thanks!
I wanted to let you know that we did finally get it to work in the test app by setting two options:
o.AutoInitEnabled = false;
-and-
o.iOS.iOS18Workaround.Enable = true;
For the first one, looking through your source, it looks like this would be false by default, so I am unsure this has any impact. The second one seems to target just iOS 18 and only within a set duration and seems to have been a fix for duplicate/double messages. No idea why these would make it work. We are now testing one -or- the other, but I wanted to let you know so you don't spend any time diagnosing our test app at the moment.
Also, wanted to let you know... the iOS18Workaround.Enable looks like it should be iOS18Workaround.Enabled (with a 'd'). Just so you can fix this in your sample whenever.
Interesting. Maybe I should set AutoInitEnabled to false by default.
iOS18Workaround.Enable is true by default. No need to set it explicitly.
Thank you for your patience as we got this figured out. It turns out it was totally a timing issue with iOS. We found that the two flags mentioned above actually had no impact on it and ended up being the red herring in our tests.
If we put a 2 second delay between registering a device and grabbing the token, the token is a newly generated value. If we do anything less than that, we run the risk that the token will be a stale one from a previous install. It probably becomes stale when we register to receive a new one is our guess.
Is this something that you have run into before? We request permission, register the device and grab the token in the same method called after login. This is the flow the application has used for years and any change to that would take a series of meetings and approvals through our leadership and business teams.
Is there something that can be done in the plugin itself so we do not need this workaround in code? Just curious if this is something that could be done.
Thanks!
Ughh, that surprises me a bit. I have to elaborate where the root of this problem could be. I remember that there was such a timing issue in the old xamarin plugin - but I thought I eliminated this 'race condition' during a refactoring. Obviously it's still there.
Ughh, that surprises me a bit. I have to elaborate where the root of this problem could be. I remember that there was such a timing issue in the old xamarin plugin - but I thought I eliminated this 'race condition' during a refactoring. Obviously it's still there.
Please let us know if there is anything we can provide to assist.
Thank you for your patience as we got this figured out. It turns out it was totally a timing issue with iOS. We found that the two flags mentioned above actually had no impact on it and ended up being the red herring in our tests.
If we put a 2 second delay between registering a device and grabbing the token, the token is a newly generated value. If we do anything less than that, we run the risk that the token will be a stale one from a previous install. It probably becomes stale when we register to receive a new one is our guess.
Is this something that you have run into before? We request permission, register the device and grab the token in the same method called after login. This is the flow the application has used for years and any change to that would take a series of meetings and approvals through our leadership and business teams.
Is there something that can be done in the plugin itself so we do not need this workaround in code? Just curious if this is something that could be done.
Thanks!
Hello, we have the same problem. Did you apply this modify? [Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")] [BindingImpl(BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)] public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) { IFirebasePushNotification.Current.RegisteredForRemoteNotifications(deviceToken); Thread.Sleep(3000); }
Just want to make sure that you await the RegisterForPushNotificationsAsync() method before you read the Token property. Can you confirm? Also, can you share some code that produces the issue. I can imagine what you mean, bit just to be very sure that I reproduce the issue properly. A small sample repro app would be wonderful.
Just wanted to add to this as another person having trouble with notifications on ios. I've compared my code to the sample project as closely as possible, the biggest difference is that I'm using AppShell and injecting the IFirebasePushNotification dependency into that rather than a view model. That shouldn't be a problem, right? Otherwise, I can't see anything I'm doing differently from you. If my app is in the background, I'm able to receive notifications just fine, and the TokenRefreshed event is being fired correctly, but none of the Notification* events seem to work for me. It's all working fine on Android, and I was able to make your sample app work for me when inserting my own GoogleService-Info.plist file and manually copying the token to my server. Have you got any ideas what might be going wrong? If need be I can try and create a sample app that reproduces the issue
Just for clarification: we awaited the RegisterForPushNotificationsAsync(). Using the latest stable version (3.0.28) notifications for Ios seems not working, but using the latest pre-release (3.1.16-pre) it works correctly
Ok good to hear that the 3.1.16-pre is working. There are a lot of improvements in this 3.1.x and I plan to release it as stable release soon.
Update: with the last pre-release (3.1.16-pre) iOS notifications are working good, but in Android we do not receive foreground notifications. It seems related to the issue #110
Update: with the last pre-release (3.1.16-pre) iOS notifications are working good, but in Android we do not receive foreground notifications. It seems related to the issue #110
We also updated to 3.1.16-pre and it fixed our iOS issue... but, Android now fatally crashes on startup with the following:
'Assertion at/_w/1/s/src/mono/mono/metadata/object.c:4410, condition 'is_ok (error)1 not met, function:mono_unhandled_exception_internal, (null) assembly:System. Private.CoreLib.dll type:TypelnitializationException memben(null)
... as well as a few other log entries.
This is only happening in a release build signed and packaged for distribution. Will not happen when running a debug or local release build.
Let me know if you need more log entries to help.
TypelnitializationException: Did you do a complete clean-rebuild? I'd recommend to close the solution and remove all bin/obj folders. Have a look at the clean.bat/clean.sh files in this project.
@seanjaeger73 could you meanwhile figure out what the problem was?
Hi, i just tested the pre-release 4.0.20-pre and version 3.2.11 - iOS Pushnotifications work for fine for as long as the app is in background. As soon as the app is in foreground i am not receiving any notifications anymore - neither the NotificationReceived nor DidReceiveRemoteNotification in appdelegate is firing. It seems like iOS doesnt let my app handle the notificaiton itself because also the NotificationOpened is not firing when i tap on a notification. But the RegisteredForRemoteNotifications is firing on startup.
Is this only occuring in my project? Thanks in advance
Update: I found out what was causing the problem: Having also another NUGET package in use like Plugin.LocalNotification keeps the foreground functionality of this package from working as intended. Without it its working, only that I dont get system notifications when the app is in foreground.
Another Update: To get iOS foreground notifications to work dont forget to set the PresentationOptions in mauiprogram like this:
options.iOS.PresentationOptions = UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Sound | UNNotificationPresentationOptions.Badge;
Alternatively if above is not working, then the AppDelegate needs to be inheriting from IUNUserNotificationCenterDelegate and in FinishedLaunching the delegate should be assigned like this UNUserNotificationCenter.Current.Delegate = this;
Last step is to include additional overrides WillPresentNotification and DidReceiveNotificationResponse
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, [BlockCallback] Action<UNNotificationPresentationOptions> completionHandler)
{
System.Diagnostics.Debug.WriteLine("iOS: WillPresentNotification called");
// Get notification data
var userInfo = notification.Request.Content.UserInfo;
// Forward to Firebase plugin (optional, depending on if you want to process it there)
IFirebasePushNotification.Current.DidReceiveRemoteNotification(userInfo);
// IMPORTANT: This tells iOS to show the notification even when app is in foreground
if (UIDevice.CurrentDevice.CheckSystemVersion(14, 0))
{
completionHandler(UNNotificationPresentationOptions.Banner |
UNNotificationPresentationOptions.Sound |
UNNotificationPresentationOptions.Badge);
}
else
{
completionHandler(UNNotificationPresentationOptions.Alert |
UNNotificationPresentationOptions.Sound |
UNNotificationPresentationOptions.Badge);
}
}
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, [BlockCallback] Action completionHandler)
{
System.Diagnostics.Debug.WriteLine("iOS: DidReceiveNotificationResponse called");
var userInfo = response.Notification.Request.Content.UserInfo;
// Forward to Firebase plugin
IFirebasePushNotification.Current.DidReceiveRemoteNotification(userInfo);
completionHandler();
}
Better don't set UNUserNotificationCenter.Current.Delegate by yourself as this leads to unpredictible behavior. The plugin sets UNUserNotificationCenter.Current.Delegate to it's own internal implementation (see UNUserNotificationCenterDelegateImpl).
Have a look at the AppDelegate.cs in the sample app. There are some calls that need to be redirected to the plugin in order to make it work smoothly:
RegisteredForRemoteNotificationsFailedToRegisterForRemoteNotificationsDidReceiveRemoteNotification
Yes thank you I already noticed it - works fine now.