Can't get notification response for push notifications on iOS
We are using the LocalNotification plugin for local notifications in our app, and it works great! We are also using Firebase push notifications, and now we are implementing support for performing different actions in the app when the user taps different push notifications.
To achieve this, we have implemented DidReceiveNotificationResponse() in our AppDelegate and use data in response.Notification.Request.Content.UserInfo to know which notification type the user has tapped. The problem is that our implementation of DidReceiveNotificationResponse() never gets called when the LocalNotification plugin is enabled. I suspect the reason is that the plugin also implements this method.
We have also tried to use the NotificationTapped event from the LocalNotification plugin. This event does get called when the user taps the push notification, however, the Request member of the NotificationEventArgs parameter is null, so there is no way for us to know which push notification that was tapped.
Is there any way we can get our implementation of DidReceiveNotificationResponse() to be called when using the plugin? Or would it be possible to update the plugin to pass the Content or UserInfo data from the push notification in the NotificationTapped event? Or do you have any other suggestions on how to solve this?
Note: This is only a problem for us on iOS. On Android, we get the data we need in MainActivity.OnNewIntent() when the user taps a push notification.
@AntAttakk Can you Please attach a sample project?
@AntAttakk I suspect the notification you request does not deserialize to type Plugin.LocalNotification.NotificationRequest that could be why Request member of the NotificationEventArgs parameter is null
@thudugala, thanks for your reply. I will see if I can create a sample project. I am not sure if I can share the project on the Firebase console, but I will have a look.
But in the meantime, do you know if there is any way to configure the plugin so it allows the call to DidReceiveNotificationResponse() to get through to our code?
@AntAttakk I have done some changes. but it's not published. Can you try referencing the project directly?
@thudugala, I have now tested with your latest changes in the repo. The change I can see is that now, the NotificationTapped event is not fired anymore when I tap the push notification. But our implementation of DidReceiveNotificationResponse() is still not called. So our app still can't handle the tap event and identify which notification was tapped.
I will continue to investigate now that I have the source code and let you know if I find anything interesting.
I have managed to implement a workaround that allows my implementation of DidReceiveNotificationResponse() to get called and still use the LocalNotification plugin as intended. Maybe it can be useful for someone else that uses both push and local notifications.
Step 1: Initialize the LocalNotification plugin before assigning my own UNUserNotificationCenter delegate.
Step 2: Save a reference to the plugin's UNUserNotificationCenter delegate.
Step 3: Assign my own UNUserNotificationCenter delegate.
Step 4: In my implementation of WillPresentNotification() and DidReceiveNotificationResponse(), I handle my push notifications and also forward the call to the plugin's delegate I stored earlier, so it can handle local notifications.
Code snippets from my AppDelegate:
private IUNUserNotificationCenterDelegate? localNotificationDelegate;
private void InitNotifications()
{
// Initialize the LocalNotification plugin before we initialize our own UNUserNotificationCenter
// delegate, to avoid that the plugin overwrites our delegate.
var ignore = Plugin.LocalNotification.NotificationCenter.Current;
// Then store the plugin's delegate so we can forward UNUserNotificationCenter calls to it.
localNotificationDelegate = UNUserNotificationCenter.Current.Delegate;
// Assign this class (AppDelegate) as the actual UNUserNotificationCenter delegate
UNUserNotificationCenter.Current.Delegate = this;
}
// This method is called if a notification (push or local) is about to be displayed
// when the app is in the foreground.
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification,
Action<UNNotificationPresentationOptions> completionHandler)
{
// Forward call to LocalNotification plugin,
// but don't let it call the completionHandler because we want to call it ourselves.
localNotificationDelegate?.WillPresentNotification(center, notification,
(UNNotificationPresentationOptions _) => { });
// Tell the system to display the notification
completionHandler(UNNotificationPresentationOptions.Alert);
}
// This method is called when the user taps a notification (push or local).
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
// Forward call to LocalNotification plugin,
// but don't let it call the completionHandler because we want to call it ourselves.
localNotificationDelegate?.DidReceiveNotificationResponse(center, response, () => { });
// Code for handling push notification goes here
completionHandler();
}
@thudugala, any thoughts? Maybe a future version of the plugin could accept a UNUserNotificationCenter delegate parameter somewhere. I could then pass my AppDelegate to the plugin and it could forward any calls it can't handle to me.
@AntAttakk can you try 9.2.1-preview01
please extend UserNotificationCenterDelegate and create your own cutom UserNotificationCenterDelegate . then set it using SetCustomUserNotificationCenterDelegate
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
// only call this method if you want to handel push notifications
Plugin.LocalNotification.NotificationCenter.SetCustomUserNotificationCenterDelegate(new CustomUserNotificationCenterDelegate());
// Ask the user for permission to show notifications on iOS 10.0+ at startup.
// If not asked at startup, user will be asked when showing the first notification.
Plugin.LocalNotification.NotificationCenter.AskPermission();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
@thudugala This seems like a good solution! I have tested it now, and it works in the sense that I can now get my push notifications if I call SetCustomUserNotificationCenterDelegate(). However, with 9.2.1-preview01 I don't get any local notifications anymore :/. It does not seem to matter if I call SetCustomUserNotificationCenterDelegate() or not - no local notifcations.
@AntAttakk, please try 10.0.0-preview02
@thudugala Sorry for the delay. I have now tested the latest version (v10.0.2) and it works well! I can get my push notifications and the local notifications are handled correctly by the plugin.
I don't know why it didn't work on 9.2.1-preview01, but it may very well have been an error in my code.
Thanks for your support and your patience :)