My app schedules a local notification with two actions on a specific time.
By the time it arrives on the phone (few hours later) my app is already in a suspended state and pressing any action button leads to nothing or simply crashes the app.
In documentation i've read that didReceiveRemoteNotification method works for handling such tasks and waking up the app from the suspended state, but i have no idea how to implement it properly for actions.
Thank you!
didReceiveRemoteNotification is called when you receive a push notification via APNS. You should be using a handler for didReceiveLocalNotification in your AppDelegate.
Related
I did some research on lots of stackoverflow issues and websites in trying to figure out how do the iOS push notifications influence AppDelegate lifecycle methods and when is which method (not) getting triggered. Main focus of the research was on "standard" iOS push notifications (with alert field) and silent ones (with just content-available set to 1) and on AppDelegate's application:didReceiveRemoteNotification and application:didFinishLaunchingWithOptions methods.
I don't want to ask lots of questions for different scenarios, but would rather try to write down the statements about different test cases I tried and ask you after that:
Is there any statement that is wrong and if yes, which one and why?
Scenario 1: App has been used and put to background by tapping the home button.
If standard push notification is sent, in the moment of push notification arrival, none of the methods gets triggered, app remains inactive in background. Once push notification has been tapped and app got opened because of it, application:didReceiveRemoteNotification method got called and application:didFinishLaunchingWithOptions doesn't get called. I tested this scenario right after putting the app to background and also after an app being in background for more than an hour - same behaviour. I guess that if for some reason iOS decided to kill my app while being in background, this test case becomes like Scenario 2, statement 1 from below, right?
If silent push notification is sent, in the moment of the push notification arrival, application:didReceiveRemoteNotification method got called and application:didFinishLaunchingWithOptions doesn't get called.
Scenario 2: App has been used and killed by swiping it out of the list of running apps.
If standard push notification is sent, in the moment of push notification arrival, none of the methods get triggered, app remains killed. Once push notification has been tapped and app got opened because of it, application:didReceiveRemoteNotification method got called and application:didFinishLaunchingWithOptions doesn't get called.
If silent push notification is sent, none of the methods gets triggered since silent push notifications fail to be sent to the app that got killed. After opening an app after notification is sent, application:didFinishLaunchingWithOptions gets called as part of the normal flow and without any push notification information. application:didReceiveRemoteNotification doesn't get called.
If you can maybe think of some other real life scenarios that I maybe forgot to mention, I would be really grateful to find out about them and what happens in those cases.
Cheers
Update #1
Thanks to Sandeep Bhandari for the update and additional scenarios. I forgot to mention in my original question that I was exploring scenarios in which application is arriving to the app that is currently not in the foreground for whatever reason.
Adding Sandeep's scenarios to the list:
Scenario 3: App is being used and push notification arrives.
If standard push notification is sent application:didReceiveRemoteNotification method will get called. application:didFinishLaunchingWithOptions will not get called.
If silent push notification is sent application:didReceiveRemoteNotification method will get called. application:didFinishLaunchingWithOptions will not get called.
Scenario 4: App being alive in background.
If standard push notification is sent application:didReceiveRemoteNotification method will get called. application:didFinishLaunchingWithOptions will not get called.
If silent push notification is sent application:didReceiveRemoteNotification method will get called. application:didFinishLaunchingWithOptions will not get called.
From an experience and digging alot on the iOS push notification. App
being in foreground or alive in background. both situations triggers
same delegate methods. only didReceiveRemoteNotification.
The silent push notification have a different handler: (content-available 1 means silent notification)
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
}
When app is dead. didReceiveRemoteNotification never called for regular push notification. It must be handled in didFinishLaunchingWithOptions as following:
// handle notification when app is closed.
let notification = launchOptions?[.remoteNotification]
if notification != nil {
self.application(application, didReceiveRemoteNotification: notification as! [AnyHashable : Any])
}
Additional information:
To test receiving push notification when app is killed. remove from the list that appears when double tapping home button?
The proper way to see the logging and do debugging is by editting the run scheme and selecting Wait for executable to be launched:
Run the app from the xcode. Then send push notification from server and then tap the notification from notification center.
I don't see any issue in the statement you made there, but I believe you missed to iterate over two more scenarios that I can think of.
App is in foreground and receives the push notification : didReceiveRemoteNotification gets called as soon as APNS gets delievered to iOS and you can handle it by checking application state in didRecieveRemoteNotification Method.
App being alive in background : I believe you are aware of background modes of iOS. If app is making use of expiration handler, app will be alive even if you put it to background by tapping on home button. Duration the app lives in background depends on various factors (some tutorials say app remains alive for 3 mins which I can't guarantee) Even in this case didReceiveRemoteNotification gets called as soon as APNS gets delievered to iOS. Only this time app wont be in foreground but yet its alive!!!
I want to auto run a function once the local notification gets triggered in iOS. didReceiveLocalNotification comes in handy in this scenario only when the app is in the foreground. But once the app is in the background, didReceiveLocalNotification has no affect. With some research I found out didReceiveLocalNotification was meant to run in foreground only.
So, is there any other way to achieve what the scenario demands? My app strictly requires local notification so I can't use push notifications and its didReceiveRemoteNotification.
I want to perform some task when local notification fired(assume application is in background/suspended but not in foreground) without taping user on notification. How it possible??.
i am not able to get delegate in application:didReceiveLocalNotification: in case of application is in background/suspended and Local Notification fired.
Please any one can suggest some solution.
Thanks in advance.
The didReceiveLocalNotification method is only called when you application is running in the foreground. If you see a badge and click on the App to start it, then you need to process the local notification using application:willFinishLaunchingWithOptions: (or application:didFinishLaunchingWithOptions:) To get at your local notification in either of these two methods, use UIApplicationLaunchOptionsLocalNotificationKey as a key to the options dictionary.
If your app is in suspended state, you won't be able to know that the notification is fired.
Is there any way at all for the app to handle a local notification if it's in the background? With application:didReceiveLocalNotification: the app must be in the foreground. Remote notifications have application:didReceiveRemoteNotification:fetchCompletionHandler: for handling notifications from the background. Any idea?
A local notification only wakes up an app that is in the background when the user chooses to enter the app via the alert. Background handlers like for remote notifications are not available. The primary intention of local notification is to act as a reminder for a timer or calendar-event, etc., I'm sure you can solve your problem on another way.
This is my scenario:
My application is not launched yet at that time app receives push notification from APN which delegate method get called;
what I read:
1. If app is in background or foreground DidReceiveRemoteNotification get called.
2. If app is not launch yet then the notification will be received in banner if i click on it. App will launch from didFinishLaunching with notification option.
You can try silent push notification. If app is in killed state, slient push notifications will be called.
Silent push will call delegate in any state.
you need pass: 'content-available' => '1' with the payload for silent notification.
Just the limit is it supports ios7 and higher.
if i understand your question correctly then solution below
when your application is not launched yet (not runnable state) that time there is not delegate method called (there is no delegate method available.)
if you want to do something after receiving push notification at that time (not runnable state or suspended state) IOS 7 provide two method
" setMinimumBackgroundFetchInterval: "
"application:performFetchWithCompletionHandler:"