While the device is powered on, is it possible for iOS to automatically terminate my app (calling applicationWillTerminate:) while it's in the background?
I'm also curious what happens in two other cases, three in total:
Device is powered on
Device is powered off
Device loses battery
I'm asking because I want to know how often applicationWillTerminate: is likely to get called. I want to know this because that's where I'm registering for remote notifications. And if there's a failure sending the device token to the server, I want to know how likely it is that that method will get called again (i.e., retry sending the device token to the server).
If your application supports multitasking (the default for anything linked against iOS 4.0+), this method will almost never be called. The documentation says it may be called in cases where the application is running in the background and the system wants to terminate. However, in my experience, I've only ever seen this actually called when running a music app that's actively playing music in the background and the system is jettisoning everything. In cases where I have background tasks running (not music, but short-term background tasks), I've seen the app terminated without this method being called.
I wouldn't ever rely on this being called and try and do all the clean-up you need to do in your delegate methods for transitioning into the background and your background task completion blocks (which do get executed for at least a few seconds before the app gets jettisoned).
Not only can iOS terminate your app automatically, but the user can kill it manually. In fact, the only time the user can kill your app is when it's in the background. Furthermore, when your app is "in the background" it's more likely to be suspended than actually running, so don't count on doing a lot of processing when you're not the foreground app.
As for how likely it is that you'll get -applicationWillTerminate:, that'll depend on the user and how they're using their device. You should handle it appropriately when you get it, and go about your business otherwise.
When memory is running low, iOS can shut down your app, calling applicationWillTerminate.
The docs say this about the method:
... However, this method may be called in situations where the application is running in the background (not suspended) and the system needs to terminate it for some reason.
Check out iOS Developer Library : iOS App Programming Guide : App Termination.
Related
I want to count costumer time(like this 00:20:04). But background app can work only 3 min.
I have timer for it, and I can count with NSDate how many seconds app be close. But don't know how call this func.
So my question is: How app can understand when app in background and stop work, and how understand when return to app?
Short answer:
Save current time when user start counting and calibrate it in applicationWillEnterForeground: , in fact you can just calibrate it in your code of setting up timer.
Long answer:
You won't receive any notification if your app is in suspend mode and then terminated.
Apps must be prepared for termination to happen at any time and should not wait to save user data or perform other critical tasks. System-initiated termination is a normal part of an app’s life cycle. The system usually terminates apps so that it can reclaim memory and make room for other apps being launched by the user, but the system may also terminate apps that are misbehaving or not responding to events in a timely manner.
Suspended apps receive no notification when they are terminated; the system kills the process and reclaims the corresponding memory. If an app is currently running in the background and not suspended, the system calls the applicationWillTerminate: of its app delegate prior to termination. The system does not call this method when the device reboots.
In addition to the system terminating your app, the user can terminate your app explicitly using the multitasking UI. User-initiated termination has the same effect as terminating a suspended app. The app’s process is killed and no notification is sent to the app.
However you can use these method of AppDelegate to get notified when your app is launched, entering background or foreground:
application:willFinishLaunchingWithOptions:—This method is your app’s first chance to execute code at launch time.
application:didFinishLaunchingWithOptions:—This method allows you to perform any final initialization before your app is displayed to the user.
applicationDidBecomeActive:—Lets your app know that it is about to become the foreground app. Use this method for any last minute preparation.
applicationWillResignActive:—Lets you know that your app is transitioning away from being the foreground app. Use this method to put your app into a quiescent state.
applicationDidEnterBackground:—Lets you know that your app is now running in the background and may be suspended at any time.
applicationWillEnterForeground:—Lets you know that your app is moving out of the background and back into the foreground, but that it is not yet active.
applicationWillTerminate:—Lets you know that your app is being terminated. This method is not called if your app is suspended.
read iOS app life cycle and UIApplicationDelegate Protocol Reference for more detail.
So here is the issue I am facing. Certain portions of the application I am building open some c network sockets that allow connections to various servers/services. However, if the application goes to sleep, these socket connections are lost, and error out when trying to reload them. So what I want to do is basically notify the user when the app launches again, that the application needs to be restarted. The main question is, can I present them with a button that will kill the app by using exit(0) without my app getting rejected?
Apple says that the user should be in control of when the app is killed, and in this case I see that they are, but I am not sure of Apple's opinion on this. Has anyone else used this? Have you been rejected for this? Thanks in advance for any advice!
EDIT:
Thank you everyone for your advice. I am trying to take everything into consideration, but because the app needs to be submitted ASAP, I just need to know, if we can not get another solution, if the above proposed solution, will get rejected or not.
Your application delegate receives notifications when significant events affect the life of the application. Rather than ask your user to recreate a session, you should attempt to discontinue network operations and then resume them at the appropriate times in the application's lifecycle automatically.
You can gracefully kill network sockets (amongst other things) in any number of places as the application prepares to exit or enter the background via callbacks in your application delegate:
applicationWillResignActive:
applicationWillEnterBackground:
applicationWillTerminate:
Potentially reconstruct sockets in:
applicationDidBecomeActive
applicationWillEnterForeground
Have you tried not allowing the app to run in the background? Then it will be killed whenever the user exits to the home screen. This might be a bit aggressive, but would solve the problem. From Apple's opting out of background execution:
"If you do not want your application to remain in the background when
it is quit, you can explicitly opt out of the background execution
model by adding the UIApplicationExitsOnSuspend key to your
application’s Info.plist file and setting its value to YES.
When an application opts out, it cycles between the not running,
inactive, and active states and never enters the background or
suspended states.
When the user taps the Home button to quit the application, the
applicationWillTerminate: method of the application delegate is called
and the application has approximately five seconds to clean up and
exit before it is terminated and moved back to the not running state."
See also: How to prevent my app from running in the background on the iPhone
The documentation is pretty explicit about this, "There is no API provided for gracefully terminating an iOS application." See Technical Q&A QA1561
How do I programmatically quit my iOS application?.
To be blunt, terminating an app to cleanup a socket is just like dealing with memory management by forcing an app to exit instead of calling release.
What about bringing up a modal view controller telling the user to quit the application? You could make this view controller without any dismiss button, so the user is obligated to kill the app.
I am developing an iphone application and I think that it's business logic requires a service to be always running in background.
The service needed is to get the acceleration of the device and notify or perform a certain action when that acceleration becomes a certain value.
Is that allowable in the Apple policies, or is there any idea about a solution?
What cydia development possibilities to help me ?
Dbramhall left out one important thing:
You can't guarantee that your app won't be killed, the OS can kill apps that are in the background at will if it requires more memory.
So if at all possible i wouldn't rely on making sure it can run its process in the background and before you ask "How can i stop this?". Well you shouldn't I've never tried it myself because i don't know the effects it has on the OS.
Also if you stop it from being killed in the Background, if it is going to be on the app store then it won't pass evaluation process, because it breaks the OS
Well, an application can run in the background and Apple perfectly accepts this however the user will obviously be be able to close the application (or should be able to) via the multi-tasking bar and this will end the application. Period.
Apple will not accept an application that runs constantly regardless of whether the user has is in background state as this drains the battery, heats the device etc. So an application can run in the background so long as the user can quit it when close it from the multi-tasking bar however it cannot continue to run after the user closed it via multi-tasking - if it does continue, Apple will reject the application.
Also, see 2.16 of the Apple Store review guidelines: https://developer.apple.com/appstore/resources/approval/guidelines.html#functionality
I've just been reading this post on notifications being sent to apps running in the background :
Not getting didReceiveMemoryWarning when app is in the background
My question is that since an app in the background will not act on a didRecieveMemoryWarning until it enters the foreground again, what is the recommended way to free up memory in your app if it is running in the background when the memory notification is sent - or is this not possible ?
In iOS 4.0 and later, - (void)applicationDidEnterBackground:(UIApplication *)application method is called instead of the applicationWillTerminate: method when the user quits an application that supports background execution.
You should use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
You should also disable updates to your application’s user interface and avoid using some types of shared system resources (such as the user’s contacts database). It is also imperative that you avoid using OpenGL ES in the background.
Your implementation of this method has approximately five seconds to perform any tasks and return. If you need additional time to perform any final tasks, you can request additional execution time from the system by calling beginBackgroundTaskWithExpirationHandler:. In practice, you should return from applicationDidEnterBackground: as quickly as possible. If the method does not return before time runs out your application is terminated and purged from memory.
If your app is running in the background (because it is, for example, a Voice over IP app that is allowed to run in the background), it will receive memory warning notifications in the same way as if it were running in the foreground, and you should deal with them accordingly.
However, if your app is suspended in the background, it won't receive memory warnings or other notifications. Your job is to free as much memory as possible before your app enters the background. Once you're in the background, you have no way to do anything anymore. The OS will decide whether to kill your app or not (without notifying you again) at its discretion.
I have an app that will run in the background but there is one case where I do not want that to happen, can I achieve this programmatically?
I know I can opt out by changing this plist value but what about at run time?
Add the variable UIApplicationExitsOnSuspend (Application does not run in background) to your applications plist and assign the value YES.
You can close the app by calling exit(0) in applicationDidEnterBackground.
You can't use exit(0) b/c apple does not allow you to close the app without user knowing it.
From Technical Q&A QA1561 How do I programmatically quit my iPhone application?.
There is no API provided for gracefully terminating an iPhone
application. Under the iPhone OS, the
user presses the Home button to close
applications. Should your application
have conditions in which it cannot
provide its intended function, the
recommended approach is to display an
alert for the user that indicates the
nature of the problem and possible
actions the user could take - turning
on WiFi, enabling Location Services,
etc. Allow the user to terminate the
application at their own discretion.
Calling exit() is discouraged, and not informing the user that the app is going to terminate is also discouraged. So you need to get the OS to kill your app (as it normally would do over a long enough period of operation) while simultaneously informing the user. One way of doing this, while using only legal APIs, is to dirty absolutely as many memory pages as possible (malloc and bzero), then call Safari with a URL to a hoggish website explaining why the app is going to quit. Safari will require enough memory to display the website that your app will be terminated by the OS, just as the user is being properly informed.
Sleeping until the OS kill timer kills your app will also kill your app, but this non-responsive delay will lock up the UI, which isn't a good user experience.