Swift didReceiveRemoteNotification firing while in app - ios

Here is my code for didReceiveRemoteNotification:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
print("notification recieved: \(userInfo)")
// Pass push notification payload to the shared model
let payload: NSDictionary = userInfo as NSDictionary
if let variable = payload["variable"] as? String {
NotificationManager.SharedInstance.handleVariableNotification(variable)
}
}
The code works and properly does what I want it to when I click on the notification from outside the app.
My issue is: if I get a notification while I'm currently in the app, it still runs the code from the notification and overrides anything the user is currently doing in the app
I only want the code to run if the user clicks on the notification, not automatically if I'm already in the app.
Thanks in advance!

Wrap your code in:
if (application.applicationState != .active){}
It will check if you are currently in the app, and fires the code only if the app was inactive or in the background.

Inside your didReceiveRemoteNotification delegate method:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
switch application.applicationState {
case .active:
print("Application is open, do not override")
case .inactive, .background:
// Pass push notification payload to the shared model
let payload: NSDictionary = userInfo as NSDictionary
if let variable = payload["variable"] as? String {
NotificationManager.SharedInstance.handleVariableNotification(variable)
}
default:
print("unrecognized application state")
}
}
Also if your application is being launched via user opening a remote notification sent by your application you will need to do this inside your app delegate didFinishLaunchingWithOptions method:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Check to see if launchOptions contains any data
if launchOptions != nil {
// Check to see if the data inside launchOptions is a remote notification
if let remoteNotification = launchOptions![UIApplicationLaunchOptionsKey.remoteNotification] as? NSDictionary {
// Do something with the notification
}
}
return true
}

Related

Opening a url in my webview app from a notification not working when the app is coming from closed

I have a webview ios app that receives notifications and I pass a url so that when the user clicks on the notification it will open the webview to that url.
When the app is in the foreground and background it works fine. If the user gets the notification when the app is closed and not currently running then the app opens but does not go to that url
In my didReceiveRemoteNotification I detect the different states of the app but I thought that .background would work the same as not running but I guess it doesn't. How can I get the notification to open the url coming from when the app is closed?
AppDelegate.swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
let data = userInfo as! [String: AnyObject]
let state = UIApplication.shared.applicationState
if state == .background {
// background
//print("==== Active Running ====")
if let aps = data["aps"] {
let url = aps["url"]
viewController?.loadRequestnotification(for: url as! String)
}
}
else if state == .inactive {
// inactive
//print("==== Inactive Running ====")
if let aps = data["aps"] {
let url = aps["url"]
viewController?.loadRequestnotification(for: url as! String)
}
}
}
UPDATE
So with some help I have been able to use didFinishLaunchingWithOptions to call my webview, but the notification when pressed is still not opening to the url.
I use viewController?.loadRequestnotification(for: url as! String) in some other areas of my delegate that works fine. I am suspecting the return true might be conflicting the call.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
ConnectionManager.sharedInstance.observeReachability()
// Override point for customization after application launch.
FirebaseApp.configure()
registerForPushNotifications()
if launchOptions != nil {
// opened from a push notification when the app is closed
let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable : Any]
if userInfo != nil {
if let object = userInfo?["aps"] as? [String : AnyObject] {
let url = object["url"]
viewController?.loadRequestnotification(for: url as! String)
}
}
}
return true
}
didReceiveRemoteNotification won't be called while app is closed.
Try this code when your app is closed to get notification data.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
if launchOptions != nil {
// opened from a push notification when the app is closed
let userInfo = launchOptions?[.remoteNotification] as? [AnyHashable : Any]
if userInfo != nil {
if let object = userInfo?["aps"] {
let url = object["url"]")
// Now set root controller here
}
}
} else {
// opened app without a push notification.
}
}
There is one scenario like your app is not running and user click on your app's notification then following the way you can get it.
Here is code you can get it
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let notification = launchOptions?[.remoteNotification] as? [String: Any] {
if let dictionary:NSDictionary = notification as? NSDictionary{
print("Dictionary Print in didFinishLaunching :: \(dictionary)")
}
}
}
Your app can received some notification and it is in notification center but user can not click on any notification but they will open your app as normally then following is a way, you can get all notification which is received by your app.
UNUserNotificationCenter.current().getDeliveredNotifications { (notification) in
print(notification.count)
}
This is the function that called when app receives any notification.
I have used this in my chatting app.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
if application.applicationState == .active {
//Application is currently active and user receive the notification
} else if application.applicationState == .background {
//app is in background, but not killed
} else if application.applicationState == .inactive {
//app is transitioning from background to foreground (user taps notification), do what you need when user taps here
//Load your URL into webView from here
}
}
If app is open and you want to perform some action when notification is received
Use this method
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler(UNAuthorizationOptions.alert.rawValue | UIUserNotificationType.sound.rawValue | UIUserNotificationType.badge.rawValue)
}
You can also check weather the app is open from notification or not in
AppDelegate's didFinishLaunchingWithOptions
But it is recommended to keep the this didFinishLaunchingWithOptions method light as possible.
I hope this will work for you

Receiving Push Notifications on Swift with AWS Mobile Hub

I am currently developing and iOS app using Swift, which I am new to, and the code generated from AWS Mobile Hub, with AWS SNS to register devices and send notifications.
On my class AWSMobileClient I have the following code:
func didFinishLaunching(_ application: UIApplication, withOptions launchOptions: [AnyHashable: Any]?) -> Bool {
print("didFinishLaunching:")
// Register the sign in provider instances with their unique identifier
AWSSignInProviderFactory.sharedInstance().register(signInProvider: AWSFacebookSignInProvider.sharedInstance(), forKey: AWSFacebookSignInProviderKey)
var didFinishLaunching: Bool = AWSIdentityManager.default().interceptApplication(application, didFinishLaunchingWithOptions: launchOptions)
didFinishLaunching = didFinishLaunching && AWSPushManager(forKey: ServiceKey).interceptApplication(application, didFinishLaunchingWithOptions: launchOptions)
if (!isInitialized) {
AWSIdentityManager.default().resumeSession(completionHandler: { (result: Any?, error: Error?) in
print("Result: \(result) \n Error:\(error)")
}) // If you get an EXC_BAD_ACCESS here in iOS Simulator, then do Simulator -> "Reset Content and Settings..."
// This will clear bad auth tokens stored by other apps with the same bundle ID.
isInitialized = true
}
return didFinishLaunching
}
Which is called normally.
On my AppDelegate, I have the following:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
AWSMobileClient.sharedInstance.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
NotificationCenter.default.post(name: Notification.Name(rawValue: AWSMobileClient.remoteNotificationKey), object: deviceToken)
print("###--- DID REGISTER FOR REMOTE NOTIFICATION ---###")
}
Which is also called.
However, when I try sending a notification using AWS SNS, my function:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("###--- DID RECEIVE REMOTE NOTIFICATION ---###")
AWSMobileClient.sharedInstance.application(application, didReceiveRemoteNotification: userInfo , fetchCompletionHandler: completionHandler)
// This is where you intercept push notifications.
if (application.applicationState == .active) {
UIAlertView.init(title: "Notification Received", message: userInfo.description, delegate: nil, cancelButtonTitle: "OK").show()
}
}
Is never called.
Looking for a solution I read that since iOS 10 there are some chances that need to be made to deal with push notification, but I'm not sure about the correct ways.
How should I implement the code to receive the notifications?

How to detect whether user click on an alert to open the app?

I want to implement push notification on my app. I am able to send notification to the device. What I want to do is to check whether users open the app by clicking the alert. If yes, I will popup some dialog or show something different based on the content of the alert. I don't know how to do that in my application. I know there is a method as shown below I can override on AppDelegate class. This method will be called when user receives a notification. But I can't know whether user open the app by clicking the alert or not. How can I achieve it?
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
if you press the Alert on APNS on confirmation alert the following delegate will fire
if user press Allow button
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
let trimmedDeviceToken = deviceToken.description .stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<>"))
.stringByReplacingOccurrencesOfString(" ", withString: "")
print("Device Token \(trimmedDeviceToken)")
}
if user press Don't Allow button
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("Failed to get token, error: \(error)")
}
After that whenerver you recive the Notification the following delegate is called
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
{
print(userInfo) // you can get the details in here
if ( application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background ){
print("opened from a push notification when the app was on background")
}else{
print("opened from a push notification when the app was on foreground")
}
}
for sample tutorial see this
check the application state using the following condition, inside didReceiveRemoteNotification method,
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
{
if ( application.applicationState == UIApplicationState.Inactive || application.applicationState == UIApplicationState.Background ){
//Tapped from a notification and the app is in background.
}else{
//App is in Foreground...
}
}
Hope this helps.
Use UIAlertViewDelegate methods by setting tag to your alert view

How do I read the text in the notification?

I am trying to read the text in the notification, so I can assign labels values based on what the notification says. And I also need help on opening a certain view controller when the notification is clicked. How would I do this? I am very new to dealing with notifications, so any help is appreciated.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if let launchOptions = launchOptions as? [String : AnyObject] {
if let notificationDictionary = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject : AnyObject] {
self.application(application, didReceiveRemoteNotification: notificationDictionary)
print("text: \(notificationDictionary)")
}
}
return true
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
PFPush.handlePush(userInfo)
}
You can get the text of the notification with
userInfo["aps"]!["alert"]
didReceiveRemoteNotification is called
when the notif is received if the app is in the foreground
when the notif is clicked if the app was in the background
To distinguish between these cases :
if application.applicationState == UIApplicationState.Active { }
Note that there is another case you need to handle: the notif is clicked while the app is closed. In this case, didReceiveRemoteNotification is not called, but the notif will be accessible in the didFinishLaunchingWithOptions launch options :
launchOptions![UIApplicationLaunchOptionsRemoteNotificationKey]

Swift iOS: How do I handle remote notification when app is not running

How do I handle a push remote notification when the app is not running. Currently, when remote notification comes in, and my app is in foreground or background, my code is correctly handling the remote notification. But when the app is not running, and remote notification come in, I see a remote banner on top of screen, and when I tapped on it, my app get launch and go away. It doesn't seem to handle the remote notification correctly. Is this how iOS behave, or is there a way to handle it. Thanks. This is currently my code in AppDelegate.swift.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
...
println("..... application didFinishLaunchingWithOptions()")
if let remoteNotification = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
// there is a notification...do stuff...
println("dinFInishLaunchingWithOption().. calling didREceiveRemoteNotification")
self.application(application, didReceiveRemoteNotification: remoteNotification as [NSObject : AnyObject])
}
return true
}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData)
{
println("didRegisterForRemoteNotificationsWithDeviceToken")
}
fun application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError)
{
println(error)
println(error.localizedDescription)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
{
println("..... application didReceiveRemoteNotification()")
}

Resources