I am reading the iOS documentation for Scheduling and Handling Local Notifications. I am stuck on a point in the section below.
Responding to the Selection of a Custom Action
When the user selects a custom action from the notification interface,
the system notifies your app of the user’s choice. Responses to custom
actions are packaged in a UNNotificationResponse object and delivered
to the delegate of your app’s shared UNUserNotificationCenter object.
To receive responses, your delegate object must implement the
userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
method. Your implementation of that method must be able to process all
of the custom actions supported by your app or app extension.
If your app or app extension is not running when a response is
received, the system launches your app or app extension in the
background to process the response. Use the provided background time
to update your data structures and your app’s interface to reflect the
user’s choice. Do not use the time to perform tasks unrelated to the
processing of the custom action.
specifically:
If your app or app extension is not running when a response is
received, the system launches your app or app extension in the
background to process the response.
Does this mean that if a user responds to a local notification by tapping a custom action, and the app is closed (completely terminated), that the app will not be launched into the foreground? I have understood "launching an app in the background" to mean that the app would remain in the background to perform specific tasks there.
And, if the app is not launched into the foreground, why would we need to update the UI?
I am surely missing something here.
Related
I have a chat application, developed on the Xamarin.Forms platform, in which users can chat with each other. I have managed c# code and UI both in the shared project.
I have been facing problem since long in iOS platform. When the iOS app is running on screen, having foreground mode then the app can successfully receive a message which has been send by another user. When the app is running in the background mode and someone sends a message, I want to notify the user by using local notification (No Push remote notification - Because I think as my app is already running in minimized mode there is no need to wake up the app by implementing Push notification). Even I have implemented local notification successfully but the problem is,
When the iOS application heads to the background mode, the main thread (task) is paused so, when some user sends a message the app is not able to execute the code (when app is minimized) so that it won’t be able to show the local notification. But when the application is brought back to the foreground the thread/task get resumed and then ie shows up the local notification and also the message.
I already have selected the "Background fetch" property under Background Modes in Info.plist. I have also added below the line in my FinishedLaunching method
UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval(UIApplication.BackgroundFetchIntervalMinimum);
I have already worked and implemented code from below links, but didn’t worked for me.
https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/ios-backgrounding-techniques/
https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/ios-backgrounding-techniques/ios-backgrounding-with-tasks#performing-tasks-during-didenterbackground
Xamarin forms background tasks run only when app is open on ios
https://arteksoftware.com/backgrounding-with-xamarin-forms/
When an iOS application goes to the background, are lengthy tasks paused?
How to perform a simple background task on Xamarin iOS
https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/ios-backgrounding-techniques/ios-backgrounding-with-tasks#creating-background-safe-tasks
https://learn.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/
I think my issue is relate to iOS Background processing, So, does anyone has idea what to do, to execute the code when app is already in minimized mode?
Generally speaking, backgrounding is very restricted on iOS. If your app is in a certain category (e.g. Navigation, Music) you'd get extended backgrounding capabilities, but I don't believe that chat apps do. More specifically, Background Fetch is not really suitable for your problem. It is called on an irregular basis to fetch contents to be cached within your app in order to make showing contents to your users faster. Background fetch intervals may vary from 15 min to several hours (not sure about the latter).
What you need is remote notifications.
Remote notifications (also known as push notifications) let you push small amounts of data to devices on which your app is installed, even when your app isn't running.
Remote notifications are brokered via a priviliged service (Apple Push Notification service - APNs) to Apple devices and delivered in a timely manner (seconds rather than minutes or hours). Usually you'd want to keep the payload as little as possible (just send the chat ID for example) and let the app fetch its data when it's notified.
Speaking in terms of a chat application, your chat server would send the remote notification to the APNs whenever a user sends a message to the chat. The app would be notified, fetch additional data and then display the notification to the user. If the notification is tapped, the user would be taken to the chat window for the respective chat.
Please note that your app has to be registered with APNs, otherwise remote notifications won't work.
Right now I have a framework that receives a silent notification, get the data from it (custom data) and translate it into a local notification to show the alert to the user (this is donde in didReceiveRemoteNotification:fetchCompletionHandler method). I have implemented this framework on an app and everything seems to be working correctly, silent notifications are being process when the app is in background and foreground. However, when the app is killed by the user or it is not running, I cannot receive notifications because of this:
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.
The reason I use this method for showing notifications is because the payload I sent to APNS has custom data with key-values that indicate how the notification must behave.
I've been doing some research and I found that Pushkit for VoIP can do the job. However, many post suggest that this can cause app rejection.
So my question is, how can I achieve receiving remote notifications even if my app was killed and considering that data in the payload has custom information to build the notification?
Silent push notifications are unreliable: they might get delayed, delivered in groups or even not delivered at all.
If you need to modify the content of the notification before presenting a banner for the user, you should use a Notification Service App Extension. You can also share some information between your app and this extension - using app groups or the keychain - if it needs something from your app to process the notification data.
I've been working with notifications for quite a while now, and I could've sworn that userNotificationCenter(_:didReceive:withCompletionHandler:) used to only be processed if the app was opened via the notification.
However, upon looking into actionable notifications, I found this:
When the user selects an action, the system launches your app in the background and notifies the shared UNUserNotificationCenter object, which notifies its delegate. Use your delegate object's userNotificationCenter(_:didReceive:withCompletionHandler:) method to identify the selected action and provide an appropriate response.
Does this mean that the seemingly universal didReceive delegate method now works even while the device is locked?
Or must the app always be opened to actually do anything meaningful in response to notification actions (writing to local database, sending HTTPS requests, etc.)?
Yes, the delegate works even if the device is locked. The app is only woken up if the user chose an action. Also, I am not sure how much time you will get before you invoke the completion block.
Important
If your response to action involves accessing files on disk,
consider a different approach. Users can respond to actions while the
device is locked, which would make files encrypted with the complete
option unavailable to your app. If that happens, you may need to save
changes temporarily and integrate them into your app's data structures
later.
From this Delegate Method : userNotificationCenter(_:didReceive:withCompletionHandler:) notification is works when your device is locked, but if you want to perform any action.
For Example: Suppose through Notification you want to pick any phone call within application then you have to setup another things as well.
you have to set up PushKit Framework within your application . As shown in images:
In iOS, we all know that there is AppDelegate method applicationWillTerminate, and it is called when my app is closed by user when it is currently running(i.e. not in background). But I want to do something(save data, for example) when my app is terminated(closed by user or killed by OS) when it runs in background.
PS: my app can run in background.
Do you have any solutions? thanks.
Sorry but you should use applicationWillTerminate:
This method lets your app know that it is about to be terminated and
purged from memory entirely. You should use this method to perform any
final clean-up tasks for your app, such as freeing shared resources,
saving user data, and invalidating timers. Your implementation of this
method has approximately five seconds to perform any tasks and return.
If the method does not return before time expires, the system may kill
the process altogether.
For apps that do not support background execution or are linked
against iOS 3.x or earlier, this method is always called when the user
quits the app. For apps that support background execution, this method
is generally not called when the user quits the app because the app
simply moves to the background in that case. However, this method may
be called in situations where the app is running in the background
(not suspended) and the system needs to terminate it for some reason.
So if you need to save data ALSO when user manually kill the app use applicationDidEnterBackground that it's called if your app support background mode.
If you need to execute code when your app isn’t running, there are
several options open to you depending on what you’re trying to do.
Background fetch will let your app run in the background for about 30 seconds at scheduled intervals. The goal of this is to fetch data
and prepare your UI for when the app runs next.
Push notifications let your app fetch fresh data from your server. You can make a message appear on the device if you want, but it’s not
required – silent push notifications let you skip that part.
Local notifications let you display an alert to the user, along with any media attachments you want and some options for the user to
select from. If they choose those options then your app can be
launched in the foreground or background to handle them.
From:
https://www.hackingwithswift.com/example-code/system/how-to-run-code-when-your-app-is-terminated
You can also use Silent Push Notification
as I mentioned in a similar question: https://stackoverflow.com/a/57245980/6157415
I was reading how handling remote notification on developer apple guide. My questions are two:
what is the interpretation of the phrase
The notification is delivered when the application isn’t running in
the foreground
isn’t running in the foreground covers background and not running or in the background state just. Based on the interpretation, the following sentence:
the application icon is tapped on a device running iOS, the application calls the same method, but furnishes no information about the notification.
has a different sense.
The second question concerns the situation where I get two consecutive remote notifications: When I open the app in the method
application:didFinishLaunchingWithOptions:
or
application:didReceiveRemoteNotification:
I have information on all notifications or just the last?
If your application is running, either in background suspended state or foreground, the method that will get called upon receiving a notification will always be application:didReceiveRemoteNotification:.
If your application is not running at all, upon launch after receiving a notification, it will trigger application:didFinishLaunchingWithOptions: and the options will be a non-nil object containing information about your remote notification.
As far as I know, only the last notification info is available.