Here a very tricky situation: I'm writing an alarm app in swift. At the moment the alarm is fired the application will most likely be in background or killed or even worse the iPhone is locked. As soon as the alarm is fired the app should set another notification automatically while in background. I'm able to do this in AppDelegate only if the app is in foreground, but in background, I'm only able to set a notification with a nice attachment and sound, but no code is executed. I'm not able to call a method after a local notification was received in background with a locked device.
Help would be very appreciated. I'm not sure there is a solution. Thank you very much.
Reading didReceiveRemoteNotification it says that this method is called if your app is running in the foreground or background.
What you may find useful is
In addition, if you enabled the remote notifications background mode,
the system launches your app (or wakes it from the suspended state)
and puts it in the background state when a remote notification
arrives. However, the system does not automatically launch your app if
the user has force-quit it. In that situation, the user must relaunch
your app or restart the device before the system attempts to launch
your app automatically again.
So, I don't the think you can work around the killed scenario. But with background mode enabled you can at least wake the app from at most the suspended mode.
Read Apple's Background Execution article, especially the section Understanding When Your App Gets Launched into the Background. Where it says a background execution is when
A push notification arrives for an app and the payload of the notification contains the content-available key with a value of 1.
You may be able to do some or most of what you want in here.
Related
When I receive a remote notification I updated a counter that I save to UserDefaults and I also show a local notification. Everything works as expected when the app is in the foreground, background, and suspended states Ref. When the app is in the Not Running state my counter is not updated nor is my local notification shown.
It is my understanding that I should be able to receive and process Remote Notifications while the app is completely off. A few articles online claim that when a Remote Notification arrives while in the Not Running state that the application:didFinishLaunchingWithOptions: should be called followed by application: didReceiveRemoteNotification:fetchCompletionHandler: but in my case it is not.
Is it possible to receive remote notifications while in Not Running state?
If your app is a VoIP app and you are using VoIP pushes through PushKit then a push notification will launch your app from the terminated state in order to deliver the notification. If you are using standard push notifications then your app will not receive the notification if it is terminated. You can include an alert text with a 'silent' notification that will be displayed to the user in the event that your app is terminated in order to prompt them to launch your app.
First of all, it sounds like you have a silent notification set up. Once you add alert data to your push notification (information like the title, body etc.. you can find more on that here), it'll start to display on the lock screen.
Second, it's not possible for your application to launch from a push notification, silent or otherwise, if it's in the Not Running state. The documentation on this is actually incorrect, as it states that the application will only not be launched if the user has quit the app. However, this actually also applies for any circumstance under the not-running state, for example if your app has never been launched since installation/rebooting, or if it was quit due to memory (a fairly common occurrence - iOS purges apps which haven't been run recently as required).
did you check this mark when app is background?
I have implemented application:didReceiveRemoteNotification:fetchCompletionHandler:, which is necessary to run after receiving a push notification. I have also turned on "Background Fetch" and "Remote notifications" background modes. And my push notifications include the content-available flag, set to 1.
If my app is in the Active, Background or Suspended state, this function gets called appropriately and the app temporarily moves into the Inactive state. However, if my app has been purged from the Suspended state due to a low memory issue (i.e. the user has opened a number of other apps since launching my app, a fairly common occurrence), it moves into the Not Running state. At that point, it doesn't call the didReceiveRemoteNotifications function.
The documentation for this function states:
If you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
The scenario where the user force quits the app and so the app doesn't call this function is acceptable. But what I'm seeing instead is if the system terminates the app for a fairly common reason, then this function doesn't get called.
I've also tried implementing application:didReceiveRemoteNotification:, the deprecated function, to see if that gets called when the app is in the Not Running state. It doesn't.
When i reboot my phone without opening my app, and send a remote notification with 'content-available' bit, my app is not launched or invoke the delegate. But I can get the notification alert. The app was even launched for scheduled background fetch! Once I started my app by tap icon, the delegate is invoked as expected even if my app is in background or killed(not force quit).
Am I misunderstanding Apple's doc of this method or I'm missing something in my implementation?
It's running on iOS 9.3.1.
Use this method to process incoming remote notifications for your app.
Unlike the application:didReceiveRemoteNotification: method, which is
called only when your app is running in the foreground, the system
calls this method when your app is running in the foreground or
background. In addition, if you enabled the remote notifications
background mode, the system launches your app (or wakes it from the
suspended state) and puts it in the background state when a push
notification arrives. However, the system does not automatically
launch your app if the user has force-quit it. In that situation, the
user must relaunch your app or restart the device before the system
attempts to launch your app automatically again.
It looks like no matter I return UIBackgroundFetchResultNewData or UIBackgroundFetchResultNoData from performFetchWithCompletionHandler, it clears all previous notifications (local or push) for my app. This is not acceptable for me.
Anyone knows how do I do fetch and not make previous notifications cleared (disappear)?
My guess here is that you had a background fetch that was setting your badge number to 0, if that ever happens all your notifications are cleared.
Source: Apple's AppDelegate API Reference
application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
Tells the app that a remote notification arrived that indicates there is data to be fetched. Use this method to process incoming remote notifications for your app. Unlike the
application(_:didReceiveRemoteNotification:)
method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground or background. In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
If the user opens your app from the system-displayed alert, the system may call this method again when your app is about to enter the foreground so that you can update your user interface and display information pertaining to the notification.
Note: You need to make sure that the app is checking for the state before settings the application's badge number to 0. Test the below cases:
Application running, receives a notification
Application terminated, receives a notification
Launch app directly from app icon
Launch app from notification received
Knowing the difference between the 3 approached below is essential in your use case.
Checking the notification object received in application(_:didReceiveRemoteNotification:)
Checking the notification object received in application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
Checking the didFinishLaunchingWithOptions for UIApplicationLaunchOptionsRemoteNotificationKey
Silent notifications work via Background modes and content available flag, but only if the app is in background.
Is it possible to know if/when the user received the notification, even when the app is suspended(not in background) ?
The system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
Here is the relevant section from the documentation:
application:didReceiveRemoteNotification:fetchCompletionHandler:
Use this method to process incoming remote notifications for your app.
Unlike the application:didReceiveRemoteNotification: method, which is
called only when your app is running in the foreground, the system
calls this method when your app is running in the foreground or
background. In addition, if you enabled the remote notifications
background mode, the system launches your app (or wakes it from the
suspended state) and puts it in the background state when a push
notification arrives. However, the system does not automatically
launch your app if the user has force-quit it. In that situation, the
user must relaunch your app or restart the device before the system
attempts to launch your app automatically again.