Closed rpanadero closed 4 years ago
By the way, I have found out another issue related to the iOS notifications. The application is not notified by any Capacitor push notification callback when a notification is received while the application is in background. In addition, if the notification is "content-available" the application is not notified either in background or foreground.
In order to support this iOS feature it should be necessary to implement this method of AppDelegate:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0);
Hey @rpanadero,
I have found this issue too. My iOS app is not receiving FCM push notifications. It does when I send the test message to the entire app, but not individual messages, which are working on Android.
How do we implement your code you mentioned above?
However, this delegate implementation doesn't fit me because my app business requirements need another one. How could I override this implementation? If I try to register another delegate in my application AppDelegate, which is versioned, it doesn't work because Capacitor core registers its delegate later.
This is an issue for me too. Any plan on supporting custom UNUserNotificationCenterDelegate implementations anytime soon?
Thanks!
how are you doing the custom UNUserNotificationCenterDelegate
? with a plugin? custom code? could you provide a sample?
What do you need to do that the Capacitor one can't?
If you do it in the load method of a custom plugin it should be called after the CAPUNUserNotificationCenterDelegate
one and use yours.
I'm working on a plugin for the Salesforce MarketingCloudSDK (https://salesforce-marketingcloud.github.io/MarketingCloudSDK-iOS/get-started/apple.html).
As per the instructions of this SDK (and also the Apple iOS documentation*), the UNUserNotificationCenterDelegate must be set in "application(_:didFinishLaunchingWithOptions:)". The problem is, that CAPUNUserNotificationCenterDelegate sets itself as the delegate after this. So there is no way for me to set my custom delegate at the right point without it being "overwritten" by Capacitor afterwards.
* See the "Important" box here: https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate
Hi @jcesarmobile,
I tried it with custom code and it happens what @philet says. Capacitor registers his delegate after mine it is set, so we could say that yours have more priority.
My problem was the same as @philet describes above. My notifications SDK required that my application called a specific method on willPresentNotification
of UNUserNotificationCenterDelegate
, just to notify the SDK of the push reception.
Finally, as I could do that easily, I decided to just use the Capacitor Core for push notifications handling and notify the notifications SDK from hybrid side by calling a plugin method. Maybe, it is not the best approach, but I guess that it is the easiest way to avoid having the same problem we had on Cordova when we had multiple notifications plugins which overrided the same delegate methods by doing swizzling. That experience on Cordova was awful because I was always frightened of breaking something.
If you let me suggest something, I think that another possible approach could be to implement the UNUserNotificationCenterDelegate
in AppDelegate
and emit an event when the method is fired. Something similar to what you are doing with didRegisterForRemoteNotificationsWithDeviceToken
.
https://github.com/ionic-team/capacitor/blob/master/ios-template/App/App/AppDelegate.swift#L64
Like that, you could catch this event in CAPUNUserNotificationCenterDelegate
, propagate the events to the respective methods and notify the web side by the Capacitor bridge. In addition, this would allow developers to put its custom code into AppDelegate methods accepting responsibility.
On the other hand, I remember you that I also realized that you are not implementing in AppDelegate
:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0);
So, if I receive a silent push notification my application is not notified and I cannot handle it. And the same happens, if the push notification is received in background although it is a non-silent one.
Feel free to tell me anything about my suggestions.
Thanks in advance
I've sent a PR to not override the UNUserNotificationCenterDelegate if present, so people can use custom delegates if they want.
I don't like the idea of moving the whole UNUserNotificationCenterDelegate
to the AppDelegate, we would like to keep the AppDelegate as clean as possible, the other methods that we've put there was because they are AppDelegate methods, but UNUserNotificationCenterDelegate
can be any class. But we have to find a way of making easier to use a custom UNUserNotificationCenterDelegate
but at the same time make it easy to propagate the data to the Push/Notification plugins if the users want to. Will think more about it and implement it in a future PR.
I didn't have any problem receiving regular push when the app is in background or closed, but silent pushes are not supported at the moment, we will add the - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
in a future release.
Just did some testing and by doing this with a custom UNUserNotificationCenterDelegate
in AppDelegate
the Capacitor one keeps working as expected.
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping (() -> Void)) {
// Do your custom handling here
let capVC = self.window?.rootViewController as? CAPBridgeViewController
capVC?.bridge?.notificationsDelegate.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// Do your custom handling here
let capVC = self.window?.rootViewController as? CAPBridgeViewController
capVC?.bridge?.notificationsDelegate.userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler)
}
From custom plugins is even easier as they already have the bridge object and can skip the let capVC = self.window?.rootViewController as? CAPBridgeViewController
part.
Thank you very much @jcesarmobile
@jcesarmobile does your solution work for Capacitor v3?
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.
Description of the problem:
First of all, I'm sorry if this shouldn't be reported as bug report, but I need help with this matter as soon as possible.
The problem that I'm facing is related to having a custom notifications delegate on iOS. I have been having a look at Capacitor core and I have seen that there is a delegate set for
UNUserNotificationCenter
. However, this delegate implementation doesn't fit me because my app business requirements need another one. How could I override this implementation? If I try to register another delegate in my application AppDelegate, which is versioned, it doesn't work because Capacitor core registers its delegate later.On the other hand, I does be able to do what I want on Android by registering a custom FirebaseMessagingService in AndroidManifest.xml. In addition, I can even call Capacitor Push Notifications plugin to avoid breaking its implementation.
Affected platform
OS of the development machine
Other information:
Capacitor version: 1.0
node version: 11.4.0
npm version: 6.5.0
CocoaPods version: 1.7.1