I have implemented remote notifications in my app, however I have problems with didReceiveRemoteNotification:fetchCompletionHandler:.
When the phone's screen is locked, I am getting the notification. If the user swipes the notification, app comes back to foreground and didReceiveRemoteNotification:fetchCompletionHandler: is called.
But if the app is running in the foreground, didReceiveRemoteNotification:fetchCompletionHandler: is never called. What might be the reason?
I'm working on iOS 10.3.2
Which iOS version you are working on ?
There are different methods for iOS 9 and iOS 10.
Below are the ones for iOS 10
//Called when a notification is delivered to a foreground app.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
}
//Called to let your app know which action was selected by the user for a given notification.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
}
For iOS 9, make sure to register your notification in didBecomeActive
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
and in your didReceiveRemoteNotification
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
if application.applicationState == .active {
//foreground state
}
}
Best approach would be to put a debugger in didReceiveRemoteNotification and check further.
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 am using didReceiveRemoteNotification for detecting the app notification. But it is is getting fired automatically, when the app is at running state. I need the notification selection get detected when the app is at running state, rather than automatic notification detection through didReceiveRemoteNotification. Thanks in Advance
iOS 10+ provide the custom local notification for handling this type of issue when the app is running in the foreground.
In didFinishLaunchingWithOptions, add the delegate
UNUserNotificationCenter.current().delegate = self
then create an appDelegate extension and add this.
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// Print full message.
print(userInfo)
// Change this to your preferred presentation option
completionHandler([.alert,.sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print full message.
print("tap on on forground app",userInfo)
completionHandler()
}
}
For details:
Read This Tutorial
Actually I need to read those notification instead of tapping the notification banner.
I have used this code
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {}
But this function only gets called when the app is in foreground or the notification banner gets tapped by the user.
I need bunch of code to read the code in Background.
I am using OneSignal Push Notification service.
You can able get the notification responce before notification banner shows. no need tap on notification banner.
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.sound, .alert, .badge])
UIApplication.shared.applicationIconBadgeNumber = 0
alertRemoteNotification(notification.request.content.userInfo as NSDictionary
}
Though till Swift 3 we used didReceiveRemoteNotification userInfo: [AnyHashable : Any] method its working fine, but in Swift 4 its not working. Does anyone have any idea about it ?
For displaying notification while app is in foreground, use the following method.
// This method will be called when app received push notifications in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .badge, .sound])
}
According to apple documentation, you can display notification while app is running
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()
}