Handling iOS errors while app moves to background process - ios

I'm working on an Cordova mobile app, currently targets iOS platform. I would like to know how to handle errors when the user quit the app abruptly on middle by pressing the Home button. Let'say the user has clicked a button that navigates the file-system, read a file, encrypts the content and save into a different location. In the middle of the process the user has clicked the Home button and so the app has moved to background. Can I expect all the operations will complete even-though the app has moved to background or do I need to handle these cases?

I would say there are two things you need to know:
1) iOS will not perform background operations unless you explicitly tell it to do so, so in the case you described, iOS would just cancel the actions that are currently active in your app. However, you have the chance to perform some operation between the point in time where the user pressed the home button and the point in time where the app actually changed its status from active to not being active. This can be done in the AppDelegate, since this is the component that controls the lifecycle of your app. The method you use here is - (void)applicationWillResignActive:(UIApplication *)application, this gets called before your app enters the background, from the Apple docs:
This method is called to let your app know that it is about to move
from the active to inactive state. This can occur for certain types of
temporary interruptions (such as an incoming phone call or SMS
message) or when the user quits the app and it begins the transition
to the background state. An app in the inactive state continues to run
but does not dispatch incoming events to responders.
So, this would be the place to either cancel the current action or save the current state so that it can be restored later.
2) iOS allows for multi tasking, but its quite tricky and only allowed in certain cases. This means you can not perform random operations while your app is in the background.
Some of these cases are:
Core Location Update: If you are using Core Location in your app, your app can receive updates on when the GPS position of the device changes and gets the chance to perform some operations in the background based on the new GPS data
Voice Over IP: The app provides Voice-over-IP services. Apps with this key are automatically launched after system boot so that the app can reestablish VoIP services. Apps with this key are also allowed to play background audio. (from the Apple Programming Guide on Background Execution)
Background fetches: With background fetches you can perform network requests on a regular basis, however you are still not able to perform the operations at points in time that you can precisely specify, you can rather tell iOS that you want to perform network requests in regular intervals and iOS will schedule the requests for you. Here is an excellent read on background fetches.
Hope it helps!

Related

iOS background fetch

I'm little bit confused with background fetch. I read in Apple Developer documentation that fetch happens when OS decides that it should, user can't control background fetch, while on Apple Developer forum post by Apple employee says that if user kills app (double tap on home and button swipe up) background fetch wont happen, in that case user can control background fetch. So can someone please clarify to me if user kills the app with task manager will background fetch still continue in the background or it's killed at the same time as app.
Apple documentation:
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4-SW1
From the doc you link:
When a good opportunity arises, the system wakes or launches your app into the background and calls the app delegate’s application:performFetchWithCompletionHandler: method.
So, it seems that the system is able to launch in the background an app that is not running so it executes a background fetch. On the other hand, though, later in the document you can read:
In most cases, the system does not relaunch apps after they are force quit by the user. One exception is location apps, which in iOS 8 and later are relaunched after being force quit by the user. In other cases, though, the user must launch the app explicitly or reboot the device before the app can be launched automatically into the background by the system.
So, Apple's engineer is right: force quitting an app puts it into a sort of special case where background fetches are not allowed anymore.
If the user feels the need to allow background operations, he wouldn't kill the app. But when he kills it, it is only appropriate to disallow background fetch. User can only control if background fetch should happen or not by allowing it to stay in background/by killing the app. But once the app is in background, user cannot control "when" the background fetch happens. The OS determines it based on how free it is.
I think this quote (from the linked document) is the most important for the scenario you're describing:
Once configured, your NSURLSession object seamlessly hands off upload and download tasks to the system at appropriate times. If tasks finish while your app is still running (either in the foreground or the background), the session object notifies its delegate in the usual way. If tasks have not yet finished and the system terminates your app, the system automatically continues managing the tasks in the background. If the user terminates your app, the system cancels any pending tasks.

is iOS background mode needed if app works when suspended?

I need my iPhone app to do some tasks in the background when it's suspended, but I don't need to do any tasks after it's turned off. Do I need to settle UIBackgroundMode?
Yes, to execute code continuously in the background state, you need to register for a given UIBackgroundMode.
See here or here for a good source on this.
However if you just wish to perform a single background task (task completion), you don't need a background mode.
In response to your comment below, I will try to be clear:
In iOS, even in iOS 7, it's not possible to run arbitrary code when your application is in a background state indefinitely.
In simple English, - you can't just run any code you like in the background for as long as you like.
There are rules.
These rules have been relaxed somewhat in iOS 7, but it's still not totally unrestricted.
Consider your situation: You have a timer that wants to call a method on a continuous basis.
Now consider the UIBackgroundModes available (which allow you to run in the background in various situations):
audio - Only for audio based apps.
location - Only if you app is location aware, does specific location tasks
voip - VOIP (Skype etc)
fetch (Background fetch - a new iOS 7 API where the system gives you application moments to grab new content when it sees fit.
remote-notification - new in iOS 7, when the device receives a remote push notification with a certain payload, it will resume and execute a certain block of code.
newsstand-content - Only for newsstand apps
external-accessory - Only for external accessories to communicate with the device
bluetooth-peripheral Only for external BT accessories to communicate with the device (fitbit)
As you can see if you don't fall into one of these categories you can't use these modes.
If you misuse the modes Apple won't approve your application.
Finally we have 'Background task completion'
This is a way to use a UIBackgroundTask to execute any code you want in the background! Including timers that call methods! - One problem though...
This is supposed to be for 'task completion' (Facebook uploads that aren't complete, saving or processing data that should be done before the app suspends even though the user pressed the home button).
Sounds good, but you can only run in the background using this method for a maximum of 10 minutes. If you go over this time limit iOS will immediately kill your application.
So as you can see, there is no way for your application to be approved on the store and constantly run in the background with a timer that calls your method.
Sorry about that.
If you want to learn more check this out.
Use the location service and set NO location manager "pausesLocationUpdatesAutomatically" property.

How does the Navita TEM app get call log information?

How does Navita https://itunes.apple.com/us/app/navita-t.e.m.-personal/id590228620?mt=8
manage to display a call log?
If I swipe the app out of the task manager then it misses the calls, this indicates that it must presumably be using CTCallCenter's callEventHandler and is creating its own call log by saving the time/duration in response to the callEventHandler callbacks.
However if that is the case then how does it manage to do this in the background? I was under the impression that callEventHandler can only be used by apps in the foreground and not in the background?
The app is using location services, however even after disabling this it was still able to get information about the calls (provided the app isn't suspended). I though it might be using background location updates to keep itself primed to receive callEventHandler callbacks but apparently not.
The Navita app is additionally able to display call time and call duration.
The bounty will be awarded to an answer which contains sufficient, accurate and detailed information that enables me to emulate the behavior of the Navita app, specifically I must be able to write an app that can obtain the time and duration of a phone call that occurred while the app was not in the foreground, while the device's location services was turned off, and after the app had been in the background longer than the ~3 minutes granted by using beginBackgroundTaskWithExpirationHandler:
Here is what I observe with the Navita app that I want to be able to reproduce:
1) Run app
2) Task away from app
3) Go to device settings, privacy, and turn off Location Services.
4) Go to device settings, privacy, background app refresh and turn off for the app
5) Wait > 10 minutes to make sure the app is not still in the background as a consequence of using beginBackgroundTaskWithExpirationHandler:
6) Call the device from another phone, answer the phone call, then hang up.
7) Launch the app again and display the call time and duration
(This is iOS7 and unjailbroken)
Here is what I've found from Navita TEM disassembly and it's resources.
Application uses two background modes - location and audio. You can see it in the Info.plist file. When you enable phone calls logging application will also enable "alerts" and "Real-time" switches. When "alerts" enabled application infinitely loops in background "bg-sound.mp3" file which has no sound, it's just silence. Because of that it doesn't use hacks like this one How to get a call event using CTCallCenter:setCallEventHandler: that occurred while the app was suspended? . It's similar trick to location used in order to keep the app running in background and receive phone call events. Somehow this was not rejected from the AppStore.
If you are observing the call center while the app is in the background you get a set of updates when the app is brought back to the foreground. This set of data may not be as accurate as if the app had been mostly in the foreground but it does include quite a bit of info.

Implementing Long-Running Background Tasks in iOS

my client asks me to develop some app that periodically retrieves the user location & the phone battery status, and then send them to our backend server for data analysis, then feed back by push notification.
But through the app doc, I get to know that from apple ios dev doc:
For tasks that require more execution time to implement, you must
request specific permissions to run them in the background without
their being suspended. In iOS, only specific app types are allowed to
run in the background:
Apps that play audible content to the user while in the background,
such as a music player app
Apps that keep users informed of their
location at all times, such as a navigation app
Apps that support
Voice over Internet Protocol (VoIP)
Newsstand apps that need to
download and process new content
Apps that receive regular updates
from external accessories
I'm wonder if this would be feasible if we wrap this app as some navigation app so we can have long-running background tasks? Does appstore will reject on our app?
BTW, what is the definition of navigation app by Apple?
You might consider using:
[CLLocationManager startMonitoringSignificantLocationChanges];
This will cause your app to be restarted if it has been killed whenever the location changes significantly, allowing you to update the details on the server at fairly regular intervals, assuming the user is moving. This does not require any special background permission. From the docs:
If you start this service and your application is subsequently terminated, the system automatically relaunches the application into the background if a new event arrives. In such a case, the options dictionary passed to the locationManager:didUpdateLocations: method of your application delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your application was launched because of a location event.
Your other option is to configure the app as requiring continuous location updates in the background, but without knowing the primary function of the app it is hard to know if this will pass store submission or not.
https://github.com/yarodevuci/backgroundTask Check my code here I am using audio player that plays blank wav file Works perfectly on IOS 8 Battery usage around 10% in 24 hour period How to use:
var backgroundTask = BackgroundTask()
backgroundTask.startBackgroundTask() //Starts playing blank audio file. You can run NSTimer() or whatever you need and it will continue executing in the background.
backgroundTask.stopBackgroundTask() //Stops the task

Sending Application to background on iphone

Is it possible to send the application to background programmatically on iPhone?
Under iOS 4.0, your app will be put in the background if another app enters the foreground, and there are enough resources to keep your app in the background. You could send a URL to Safari, or another app that has registered for a handler, and hope that there's enough memory (etc.) that the OS puts your app in the background after it starts Safari (or whatever app handled the URL). If you are lucky (which typically happens fairly often), you will have sent your app programmatically to the background.
Of course, whether your app runs in the background, or is just suspended, depends on other things (which you have to register with iOS 4.x for).
Apple does allow apps to exit (kill themselves) programmatically. But it's meant only as a last resort for when something bad happens from which your app cannot recover.
On all other occasions, apps are expected to stay in the foreground and running until either the user presses the home button or the app opens another app, with the users consent.
Actually you don't want to kill the app, however moving it to the background and returning to the home screen would leave a very similar impression. That's why I don't think Apple would approve it and consequently doesn't offer, as far as I know, any means to move an app to the background programmatically without opening another app.
No it is not possible. Only iOS can put your application in the background.
Note that there's a lot of confusion between "background" and "inactive". An inactive application is one that is not displayed on the GUI but is still running.
Technically an application in the background isn't running; it's dormant. Depending on the mode used, a background applications can receive signals and "wake up." See Background Modes for more details: https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW22
But a background application can also get terminated at any point without warning. As a matter of fact I always treat a background application as terminated. Therefore you should always clean up your application before you enter the background, and re-initialize it when you enter the foreground.
This is a must-read on this topic: https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
check out these post
local notifications?
iPhone - Backgrounding to poll for events

Resources