iOS. Measure time in setKeepAliveTimeout:handler: while waiting for server response - ios

I am developing a VoIP app. When my app is in background I need to check if the server is still there. So I am trying to use setKeepAliveTimeout:handler: to make polls to server while app is in background.
The question is: how to ensure that I receive response or timeout within 5 seconds after I have sent poll message to server? If I don't receive response/timeout within 5 seconds the next opportunity to know that server is dead is only after keepAliveTimeout time which is not that good.
As I understand I can't setup NSTimer in setKeepAliveTimeout:handler: since we are in background (and NSTimer relies on run loop).
I see other possibility which is: make while loop and check for the current time in it. Although I would like to avoid making busy loops.
Could you please suggest me how can I achieve needed behaviour?

Related

how to handle a long wait time for data, when ios 8+ app has been backgrounded by user

I've spent a lot of time looking at the options but am still not 100% clear, so wanted to reach out for some guidance.
Scenario is this:
User submits an HTTPS request to our backend server for some data via an iOS app
Depending on the data, the first (only) request can take a REALLY long time. like, say, 10+ minutes (shocking i know)
When that payload finally does become available and is returned via the HTTPS request, we then want to use it to update the UI in background.
The assumption here is that the user has moved on to another app whilst waiting for the data to arrive (and lets also assume they haven't killed the app).
Is it possible to handle this via iOS 8+ API's without the app being force/killed by Apple when in the background ?
Could we use background task for example?
var backgroundTask: UIBackgroundTaskIdentifier
xxx.beginBackgroundTaskWithName...
etc
Before testing some code blocks we just wanted to see if someone has (a) already done this and/or (b) whether we're heading in the right direction
Thanks for your help.
You should re-think on your web service which may take almost 10 min to process. If you are not able to optimize server task processing time then below one of the idea may be help you.
You can divided your one request into multiple request to reduce processing time and get response in faster way.
Your server should sent notification to app when its done with its task. So app will came to know task is done.
I am not sure why you try to update UI when apps in background mode , you may try to update UI when users come to foreground mode from background mode.
Please check this link which show as example of long running task. Where its use a blank audio play to keep alive app background task.
You can used "Background fetch" functionality.
For learning purpose you can refer this link

swift/ios refreshing app data when in background

I'm writing a iOS/Swift application which reads data from a REST service each X minutes and updates the UI accordingly.
Now I would like that when the app is put in the background, a task keeps being invoked at X minutes intervals reading from the REST service and, in case the data just read satisfies a given condition, show a notification prompting the user to bring the app back to the foreground.
In my searches I've read that during applicationDidEnterBackground event, I should start a task with beginBackgroundTaskWithExpirationHandler.
The problem is that, if I've understood correctly, this allows a maximum of 10/15 minutes after which the app is terminated if the task is not stopped with endBackgroundUpdateTask, while I want the task to keep polling the service indefinitely (at least until the user disable it from the app's settings)
My question is:
How is this kind of functionality performed normally? Do some common solutions or best practices exist for the solution of such a problem?
Use iOS Background Fetch feature where you can specify minimum background fetch interval. But actual interval between successive invocation of your code will be determined by iOS framework. For details checkout this link: http://code.tutsplus.com/tutorials/ios-7-sdk-working-with-background-fetch--mobile-20520
I use this approach in my app and I think it is a preferred way of doing.
You can use a local notification that can be presented from the background in case your condition is met.
Correct, iOS will eventually shut down the background process, you can't enforce continuous background activity. Use the backgroundTimeRemaining property to check how much time your application has left and try to handle it as gracefully as possible by calling endBackgroundTask so that iOS does not force kill your app.
As a solution, you could think about using remote notifications with with content-available : YES, which runs the didReceiveRemoteNotification
Have a look at the Parse.com Their local datastore is an abstraction for what you are trying to acheive.
By the way, is it really necessary to refresh in the background. If call is relatively quick, there is no need to refresh until the user open's the app. Background processes like that, using the net can be quite battery consuming when the user are not on a Wifi. So consider the use case carefully!

ping server when the app is in background

I need to keep the app to send a simple GET request ("ping") to the server every minute just for it to know that user is still online. I have no problem with it while the app is active and 10 minutes after it went background using "beginBackgroundTaskWithExpirationHandler".
But how can I keep request repeated all the time unless user terminates app manually?
That's not really how it works -- it's not a Windows or a Mac app that runs continually in the background.
What you probably want to do is use the background fetch process, whereby iOS will periodically run a particular method allowing you to do network operations while your app is in the background (or not running at all).
What this won't allow you to do is ping your server exactly once every minute. But actually that's a good thing. Consuming a users battery and data allowance like that is not very user-friendly.

Is the appPaused event working properly for me? I am getting some weird behavior with my clean-up code on iOS

I have been dealing with this issue for weeks and am unsure if it is my code's fault, forge's appPaused event not triggering quickly enough, or Trigger.io's documentation not being nearly clear enough about just how little time iOS gives us to execute clean-up code.
According to the documentation regarding the appPaused event:
iOS: A short amount of time is given for execution, it is generally best to assume that callbacks and timers may not fire until the app is resumed.
My application deals with websockets and ideally I am able to send a close event to my server when a user minimizes my app, or the phone is locked. Currently, all of my clean-up code runs perfectly on Android, but on iOS, my clean-up code doesn't run until the app is resumed. The strange part is sometimes (maybe 1 out of 20 times) the iOS clean-up is correctly run right after the appPaused event is fired.
To test this I have done two things:
I make the very first thing to run after the appPaused event is fired is a message to my websocket server saying "the app is paused". 95% of the time, this message is not actually sent until the app is resumed, but the other 5% of the time my websocket server receives it right after I pause the app.
I then made it so the first thing to run after the appPaused event is fired is a line that stores Date.now() in a global variable. I then then store Date.now() in another global variable when the app is resumed, and find the difference between them. It gets interesting because around 50% of the time the Date.now() line is correctly fired right after the appPaused event is called, but the other half of the time the 2 Date.now() calls are only milliseconds a part, proving that the clean-up code was not run until the app resumed.
So, can I really only expect to sometimes have enough time after appPaused is fired to even store Date.now() in a variable? Is this what everyone else is experiencing when running their Trigger.io applications on iOS? Let me know if anyone could use more information.
Yes, appPaused is not guaranteed to fire on iOS. Note, that it may only fire when the app is resumed.
Any code you want to run on going into the background will probably not run. See the trigger io docs on events. The note on iOS needs careful reading.
That said I have a similar app to yourself dealing in websockets. What i've found is that I can leave the socket open, iOS automatically kills the socket when it suspends the app (Sometime after the paused event is received which corresponds to the ios background state). The server receives the close event and you can of course attach to that event to set any state or cleanup resources. Android requires a manual shutdown of the socket, but appPaused works in a guaranteed way when the app is put into the background.

iOS background uploading of images

I have made an application which uploads a bunch of photos to a web server. It does so by repeated html calls, using multiple AFNetworking's AFHTPRequestOperation inside an operation queue. Right now, of the user exits the application, the queue stops. However, I want to continue the uploading queue until it's done, and then let the application go to sleep like it normally does.
I know that iOS provides a background expiration handler using "beginBackgroundTaskWithExpirationHandler" . I also know that AFURLConnectionOperation which is superclass of every HTTP operation class in AFNetworking can use that using
- (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler
But is there any way of making this work with an operation queue? Will setting the expiration handler of each operation do the job properly if I want to upload, let's say 10 photos?
I would appreciate any comments on background tasks with AFNetworking, or if anyone has experienced the same problem as me.
When an app goes to background, the OS will decide whether or not to completely stop your app or give it some time to complete what it's doing. In case it wants your app to stop, the expiration handler is called. If that's happening you should suspend all your tasks as fast as possible and prepare for a complete kill of the app, because that is what will happen a very short time after (5 seconds max). Take a look here.

Resources