I want to handle tap on local notification, when the app is terminated, but there are no launch options in method application didFinishLaunchingWithOptions and no call of method application didReceive notification.
I also tried to implement two methods of UNUserNotificationCenterDelegate:
1)Handles notification, when app is in background, but not terminated:
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void
)
2)And next handles notification, when app is in foreground:
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void
)
Have no idea how to handle it...
When you tap on Push Notification on Notification Center.
OS launches your app (terminated before) then STILL delivers the action to this (Function 1)
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void
)
You can get the notification object from response like what you did.
But you may need to save temporary this data from the selected push notification, then handle it later when app is completely active with user.
Remember to call completionHandler() when you finish your logic. And, you must set UNUserNotificationCenter.current().delegate = self, before you return true in
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool`.
self here is your AppDelegate, which means you set UserNotification's delegate to a live object or initialized object.
It will be able to handle the above delegate function call (Function 1) to get your selected push notification's data.
Related
I have now integrated push notifications in my app using FirebaseNotifications. For this I use a NotificationServiceExtension for processing (CoreData, ...) and the usual methods, such as didReceiveRemoteNotification, willPresent or didReceive in AppDelegate.
The processing of the content and the display of the push notification works perfectly in all status of the app - in the background and also in the foreground.
If the app is in the foreground or in the background, but not killed, tapping on the push notification also works and the didReceive method is called and I can navigate to the desired content.
If the app is completely killed, a tap on the push notification a few seconds later starts the app, but the usual launch screen (splash screen) is not called and nothing else happens - the app remains on a white screen.
At first I suspected I had forgotten to call a completionHandler, but they are all stored and I don't find an error anywhere.
Can someone please help me, where there could still be a problem that the splash screen, then the AppDelegate and my normal ViewController, is called up.
Thank you - here is my code in the AppDelegate. Unfortunately I don't have a log because the app has to be completely killed and I therefore have no output in the Xcode console.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(UIBackgroundFetchResult.newData)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([[.alert, .badge, .sound]])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
defer {
completionHandler()
}
if response.actionIdentifier == "friends" {
print("Open button was pressed.")
// TODO: - Deep link to friends
}
completionHandler()
}
I have to locally store Title and Body of all the notifications coming in my iOS app and display those in a notifications screen. I'm able to store all the notification tapped by using these-
This gets called when the app is in not running state or killed when the push notification is tapped-
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {...}
This gets called when app is running in foreground or background and push notification is tapped-
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {...}
My question is how to store notifications without tapping on notifications.
I want to store the notifications even if the notification is dimissed/cleared by user.
I know this method is called when app is active and in the foreground and push notification comes-
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {..}
How to handle push notification data without tapping on it when the app is in background or not running state?
1- If the app isn't running then no way to wake up the app only with ( VOIP )
2- if in background then add this key to the sended payload
"content_available": true
And enable RemoteNotifications from app capabilities
When my app is not running and a user taps on the notification in the notification center, the didFinishLaunchingWithOptions function is called with push data passed into the launchOptions dictionary.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
//do stuff with push data in launchOptions dictionary
}
but also the userNotificationCenter didRecieve function is called
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
log.info()
let state = UIApplication.shared.applicationState
print(state)
if UIApplication.shared.applicationState != .active {
log.debug("exiting because app is not in active state")
return
}
let userInfo = response.notification.request.content.userInfo
//do stuff with userInfo
completionHandler()
}
In didRecieve function, how can i tell that the app was launched versus the app was already running in the background when the user tapped on the notification?
The application is active when the app is in the foreground but it is inactive when the app is in the background or was launched from the push, so i can't tell the difference.
The application didRecieveRemoteNotification looks ideal but it is only called when i send a silent push but my pushes aren't silent.
Do you have to try using willPresent function for handle your push in foreground case? Something like this
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping () -> Void) {
handlePushWhenForeground(notification?.request.content.userInfo) // implement this function
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
if UIApplication.shared.applicationState == .inactive {
handlePushWhenBackground(response.notification.request.content.userInfo) // implement this function
} else {
handlePushWhenNotActivated(response.notification.request.content.userInfo) // implement this function
}
}
I want to find out which method is triggered when a terminated application receives a notification from my server. The application is being developed through Swift 4, my Deployment Target is 10.3 and Firebase is used to send notifications to users.
I've configured my application in AppDelegate.swift:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
Messaging.messaging().delegate = self
UNUserNotificationCenter.current().delegate = self
}
Additionally, I created the extension:
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
}
}
When the app receives a notification and it's running or it's in background, the method "willPresent" is called and when the user taps on the notification and decide to open it, the method "didReceive" is called. No method is triggered if the application is terminated.
Am I doing something wrong?
So when my app is not currently open and it receives a push notification, the "didrecieveremotenotification" works perfectly fine when the banner appears and you press it. But when the app is open, no banner at all appears. I want the push notification to work when the app is open aswell.
I tried using UNNotificationCenter but lost push notifications in general.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert], completionHandler: {(granted, error) in
if (granted) {
UIApplication.shared.registerForRemoteNotifications()
} else{
print("Notification permissions not granted")
}
})
}
//Called when a notification is delivered to a foreground app.
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Swift.Void) {
completionHandler([.sound, .alert, .badge])
}
//Called to let your app know which action was selected by the user for a given notification.
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Swift.Void) {
completionHandler()
}
Update: UNUserNotificationCenter.current().requestAuthorization runs
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
when permission is granted.
however when I don't use UNNotificationCenter and use old method it doesn't fail.
Why would one method fail to register for remote notifications but the other not?
Update 2: Was working in simulator lol, that's why it was failing. However now when I run the
UNUserNotificationCenterDelegate
methods only the
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive method works and not the
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent
Update 3: I've ran out of possible things to try. What would be stopping the code from firing willPresent but not didReceive. This is brutal. Has anyone ever had this issue before?
Update 4: SOLVED. The service I'm using for the push notifications requires the user to be disconnected from the service to send the push notification. It automatically disconnects you when you're in the background, which is why that was working and it wasn't working in the foreground.
Weird way for them to configure that, I'll probably send an email.
Implement UNUserNotificationCenterDelegate delegate methods to get notification (tray at top) while app is in foreground. But it will only work with IOS 10.
In your didFinishLaunchingWithOptions method set UNUserNotificationCenterDelegate delegate like this.
UNUserNotificationCenter.current().delegate = self
Implement Delegate methods...
//Called when a notification is delivered to a foreground app.
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Swift.Void) {
completionHandler([.sound, .alert, .badge])
}
//Called to let your app know which action was selected by the user for a given notification.
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Swift.Void) {
completionHandler()
}