iOS11 handle firebase push notification when app removed from background - ios

Code :
FirebaseApp.configure()
application.registerForRemoteNotifications()
requestNotificationAuthorization(application: application)
NotificationCenter.default.addObserver(self, selector:
#selector(tokenRefreshNotification), name:
NSNotification.Name.InstanceIDTokenRefresh, object: nil)
//in iOS9 called didreceiveremote method when app is killed
let notification = launchOptions?[.remoteNotification]
if notification != nil {
self.application(application, didReceiveRemoteNotification: notification as! [AnyHashable : Any])
}
#objc func tokenRefreshNotification(_ notification: Notification) {
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
UserDefaults.standard.setPushToken(value:refreshedToken)
}
}
func requestNotificationAuthorization(application: UIApplication) {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions, completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
}
extension AppDelegate : UNUserNotificationCenterDelegate {
// iOS10+, called when presenting notification in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
NSLog("[UserNotificationCenter] applicationState: \(applicationStateString) willPresentNotification: \(userInfo)")
//TODO: Handle foreground notification
completionHandler([.alert])
}
// iOS10+, called when received response (default open, dismiss or custom action) for a notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
NSLog("[UserNotificationCenter] applicationState: \(applicationStateString) didReceiveResponse: \(userInfo)")
//TODO: Handle background notification
if UIApplication.shared.applicationState == .active {
//TODO: Handle foreground notification
} else {
//TODO: Handle background notification
}
completionHandler()
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
NSLog("[RemoteNotification] applicationState: \(applicationStateString) didReceiveRemoteNotification for iOS9: \(userInfo)")
if UIApplication.shared.applicationState == .active {
//TODO: Handle foreground notification
} else {
//TODO: Handle background notification
}
}
}
I am developing an app which has target of iOS9 and firebase push notification feature. My requirement is the app removed from background and the user tap push notification then move to a screen(Ex. AccountVC). In iOS 9 I could able to handle push notification when app is removed from background. But in iOS11 I do not know how to handle when app is removed from background. Any help will be appreciated, thanks in advance

Related

Swift 4 Firebase Cloud Messaging only works with single device

In my app I am trying to set up Push notifications Using Firebase Cloud Messaging.
When I try and send a notification using a single device and FCM key, I receive the notification. However, it does not work for User segment when I select the targeted app.
Here is my App delegate setup:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Firebase
FirebaseApp.configure()
FirebaseConfiguration.shared.setLoggerLevel(.min)
// Push notifications
application.registerForRemoteNotifications()
setupPush(application: application)
if #available(iOS 10.0, *) {
let authOptions : UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_,_ in })
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
// For iOS 10 data message (sent via FCM)
Messaging.messaging().delegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
}
UIApplication.shared.registerForRemoteNotifications()
}
#available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// iOS10+, called when presenting notification in foreground
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
NSLog("[UserNotificationCenter] applicationState: \(applicationStateString) willPresentNotification: \(userInfo)")
//TODO: Handle foreground notification
completionHandler([.alert])
}
// iOS10+, called when received response (default open, dismiss or custom action) for a notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
NSLog("[UserNotificationCenter] applicationState: \(applicationStateString) didReceiveResponse: \(userInfo)")
//TODO: Handle background notification
completionHandler()
}
// Setup APNS token for Firebase
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
#if PROD_BUILD
Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
#else
Messaging.messaging().setAPNSToken(deviceToken, type: .sandbox)
#endif
}
extension AppDelegate : MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
NSLog("[RemoteNotification] didRefreshRegistrationToken: \(fcmToken)")
}
// iOS9, called when presenting notification in foreground
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
NSLog("[RemoteNotification] applicationState: \(applicationStateString) didReceiveRemoteNotification for iOS9: \(userInfo)")
if UIApplication.shared.applicationState == .active {
//TODO: Handle foreground notification
} else {
//TODO: Handle background notification
}
}

Remote notifications from background

I am creating an app in swift which will use UNNotificationAction buttons.
I have userNotificationCenter set up properly and I can call didReceive properly while the app is open... From here I show a modal window.
The issue is that when the app is not running in foreground or background (user hasn't opened app yet) I can't get didFinishLaunchingWithOptions to parse my code when I check on launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification]
Is there a new technique for processing when a user fresh opens the app when tapping on a push notification using a UNNotificationAction?
In didFinishLaunchingWithOptions, when you discover that you are launching because of a notification, set yourself as the UNUserNotificationCenter's delegate and return false. Now your didReceive implementation will be called.
Kindly Check this code below , Hope this helps.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,CLLocationManagerDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
}
#available(iOS 10, *)
// 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
// With swizzling disabled you must let Messaging know about the message, for Analytics
Messaging.messaging().appDidReceiveMessage(userInfo)
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// print(userInfo)
completionHandler([.alert, .badge, .sound])
// Change this to your preferred presentation option
// completionHandler([])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
switch response.actionIdentifier {
case "action1":
print("Action First Tapped")
case "action2":
print("Action Second Tapped")
default:
break
}
// Print full message.
print(userInfo)
Messaging.messaging().appDidReceiveMessage(userInfo)
completionHandler()
}

How to redirect to a specific page for push notification?

I am working on ios push notification and need to redirect it to a specific page on tapping it.
How can this functionality be achieved ?
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("userInfo:-> \(userInfo)")
let redirect_flag = userInfo["redirect_flag"]as! String
if application.applicationState == .inactive {
//MARK: - code here to redirect when app is not in background or inactive
if (UserDefaults.standard.value(forKey: KEY_IS_LOGIN) != nil)
{
switch redirect_flag {
case "1":
print("redirect controller")
case "2":
print("redirect controller")
case "3":
print("redirect controller")
default:
break
}
}
}else {
//MARK: - code here to redirect when app is in background or active mode
switch redirect_flag {
case "1":
print("redirect controller")
case "2":
print("redirect controller")
case "3":
print("redirect controller")
default:
break
}
}
}
To redirect to a specific page when a notification received ,you must first handle received push notification,
To handle recieved push notification follow the steps below:
In didFinishLaunchingWithOptions set messaging delegate to self
Register for remote notification. This shows a permission dialog on first run
You need to handle notification registration for iOS 10 and before
implement didReceiveRemoteNotification to start receiving messaging , here you can handle received data, parse it and redirect ... this will be called when notification tapped for devices that run iOS lower than 10
For iOS 10 and later you can conform to UNUserNotificationCenterDelegate, and implement didReceive method.That's it
Example:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// [START set_messaging_delegate]
Messaging.messaging().delegate = self
// [END set_messaging_delegate]
// Register for remote notifications. This shows a permission dialog on first run, to
// show the dialog at a more appropriate time move this registration accordingly.
// [START register_for_notifications]
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
return true
}
Handling Recived messaged :
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print full message.
print(userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
Handle Received notifications for iOS 10 and later:
#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
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
// Change this to your preferred presentation option
completionHandler([.alert, .badge, .sound])
}
//When clicked
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: #escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
print(userInfo)
//You can here parse it, and redirect.
completionHandler()
}
}

I am working on push notification with firebase. and my "didReceiveRemoteNotification" function is not called

I am working on push notification with firebase. and my "didReceiveRemoteNotification" function is not called.i do not know why my function is not called and also payload data is not recieved in console.please resolve my issue.Thanks in advance.
**Here is my code:**
FirebaseApp.configure()
Messaging.messaging().shouldEstablishDirectChannel = true
// [START register_for_notifications]
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound],
categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
// [END register_for_notifications]
// Add observer for InstanceID token refresh callback.
NotificationCenter.default
.addObserver(self, selector:
#selector(AppDelegate.tokenRefreshNotification),
name: NSNotification.Name.InstanceIDTokenRefresh,
object: nil)
#objc func tokenRefreshNotification(_ notification: UIViewController)
{
Messaging.messaging().subscribe(toTopic: "Testing")
}
func application(_ application: UIApplication, didReceiveRemoteNotification
userInfo: [AnyHashable : Any])
{
print("userInfo\(userInfo)")
}
import UserNotifications
in didFinishLaunchingWithOptions
if #available(iOS 10, *) {
UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
application.registerForRemoteNotifications()
} else {
application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
}
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
// Enable or disable features based on authorization.
}
application.registerForRemoteNotifications()
registerForPushNotifications(application: application)
//MARK: pushNotifications methods:
func registerForPushNotifications(application: UIApplication) {
if #available(iOS 10.0, *){
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert], completionHandler: {(granted, error) in
if (granted) {
UIApplication.shared.registerForRemoteNotifications()
} else{
//Do stuff if unsuccessful...
}
})
} else { //If user is not on iOS 10 use the old methods we've been using
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print(response.notification.request.content.userInfo)
let dic = response.notification.request.content.userInfo as NSDictionary
if let aps = dic["aps"] as? [String: Any] {
print(aps)
}
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
print(notification.request.content.userInfo)
let dic = notification.request.content.userInfo as NSDictionary
if let aps = dic["aps"] as? [String: Any] {
print(aps)
}
}
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) {
// Print notification payload data
print("Push notification received: \(data)")
}
Try using the didreceiveremotenotification completionhandler method. Don't forget to enable the push notifications capability in capabilities tab of your project settings section.

iOS 10 push notifications - how does willPresentNotification and didReceiveNotificationResponse work?

Currently I have my app set up to receive push notifications in ios 9 where it works perfectly but with iOS 10 I'm not receiving them. I've looked over various responses on stackoverflow and came across this:
Push Notifications not being received on iOS 10, but working on iOS 9 and before
which appears to work for the poster. I'm not entirely sure what code I'm supposed to add under the willPresentNotification and didReceiveNotificationResponse sections. If anyone has any examples of how these sections work it will be appreciated. This is my relevant code for handling push notifications so far:
import UserNotifications
import Whisper
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
registerForPushNotifications(application)
}
//MARK: Push Notification Settings
func registerForPushNotifications(application: UIApplication) {
//check to see if phone is updated to iOS 10
if #available(iOS 10.0, *){
UNUserNotificationCenter.currentNotificationCenter().delegate = self
UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptions([.Badge, .Sound, .Alert], completionHandler: {(granted, error) in
if (granted)
{
UIApplication.sharedApplication().registerForRemoteNotifications()
}
else{
print("registering for push notifications unsuccessful")
}
})
}
else{ //If user is not on iOS 10 use the old methods we've been using
let notificationSettings = UIUserNotificationSettings(
forTypes: [.Badge, .Sound, .Alert], categories: nil)
application.registerUserNotificationSettings(notificationSettings)
}
}
//Notification handling for iOS 10
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, willPresentNotification notification: UNNotification, withCompletionHandler completionHandler: (UNNotificationPresentationOptions) -> Void) {
//Handle the notification - NOT SURE WHAT GOES HERE
}
#available(iOS 10.0, *)
func userNotificationCenter(center: UNUserNotificationCenter, didReceiveNotificationResponse response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
//Handle the notification -NOT SURE WHAT GOES HERE
}
//This is called if user selects to receive push notifications
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
// if notificationSettings.types != .None {
application.registerForRemoteNotifications()
// }
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let tokenChars = UnsafePointer<CChar>(deviceToken.bytes)
var tokenString = ""
for i in 0..<deviceToken.length {
tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
//save device token to keychain
self.deviceToken = tokenString
userInfo.sharedInstance.savePushNotDeviceToken(tokenString)
NSUserDefaultsManager.sharedManager.pushNotifications = true
//register device token to api
registerPushNotificationDevice(tokenString)
print("Device Token:", tokenString)
}
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("Failed to register:", error)
//save push notifications state
NSUserDefaultsManager.sharedManager.pushNotifications = false
}
//In- App push notifications
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
if application.applicationState == .Active {
let navigationController = self.window!.rootViewController as! UINavigationController
let alert = [String: String]()
let title = ""
let body = ""
// Default printout of userInfo
print("All of userInfo:\n\( userInfo)\n")
if let aps = userInfo["aps"] as? NSDictionary {
if let alert = aps["alert"] as? NSDictionary {
if let title = alert["title"] as? NSString {
if let body = alert["body"] as? NSString {
let announcement = Announcement(title: title as String, subtitle: body as String, image: UIImage(named: "Image"))
show(shout: announcement, to: navigationController)
}
}
}
}
}
}
}
For remote and local notification in iOS 10 we have UserNotifications.framework. To handle notification there are two delegate methods of UNUserNotificationCenterDelegate available in UserNotifications.framework. You need to do the same code you are doing in didReceiveRemoteNotification method to get userInfo.This two methods are available to handle userInfo according to your app requirements.
//UNUserNotificationCenterDelegate delegate methods to get userInfo
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
//Called when a notification is delivered to a foreground app.
let userInfo = notification.request.content.userInfo as? NSDictionary
print("\(userInfo)")
}
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
// Called to let your app know which action was selected by the user for a given notification.
let userInfo = response.notification.request.content.userInfo as? NSDictionary
print("\(userInfo)")
}

Resources