I'm using BLE connection and app needs to run in background forever. For now background mode working, but limited, after few hours system kills app without any notifications and appDelegate methods calls. I checked ram usage, and it not depend, system kills app when ram usage 60mb, and when 200mb. Also app periodically sent POST requests to server(every minute) and using location services. How to extend execution time? Is it possible to run app forever(if user not using other apps)?
The answer is NO, iOS is doing dark magic to optimise resources usage and we can't do anything about it.
Related
I'm developing an iOS app, using Codename One. I extended the SocketConnection class, in order to receive data from a server.
I tested the app on an iPhone 7s (iOS version 11.2.5 15D60) and it works fine. When I press the home button, the app suspends, but it keeps the connection with the socket server. But when the device goes into standby mode, the socket connection is closed.
Is it possible to avoid this behaviour, in order to keep the socket connected?
Short answer: No and that's a good thing.
Long answer: When an app is suspended in iOS if it uses too much resources the OS kills the app to conserve battery life. Apple does allow some apps in some cases to perform tasks in the background but even then it's under heavy restrictions that are hard to follow and change frequently.
Generally you would define a background behavior that allows you to do something in the background. E.g. in this post we discuss background fetch which allows you to keep polling a server when we are in the background. It might not work with sockets.
The "right thing" in terms of iOS would be suspending your connection when in the background and using push notification to notify the user of a potential update.
I have been investigating iOS background fetch for our enterprise applications. According to articles like this, there are limitations like having 30 seconds to download before the app is terminated and the may be (unconfirmed) a penalty where after 3 timeouts, an app gets banned from background sync. Also if the user kills the app, fetches stop happening -noted here.
The goal is to be able to retrieve data from our servers periodically when app is suspended/not running but sometimes the transfers can take minutes due to long running SQL. I don't want to implement sending periodic notifications to all users.
Before I go down the path of developing for the iOS background sync, I needed to do some due diligence and research alternatives to iOS's background sync and didn't find anything.
Has anyone seen or developed an alternative to iOS's background sync or dealt with this issue for their enterprise apps?
As an enterprise app there's nothing extra you can do except that you can use whatever background modes you want (audio, location, voip etc,) without needing to have a legitimate reason to do so.
Where this might assist is:
you could make use of a significant location change (as opposed to a regular location change) notification to run your app in the background. The problem with this is it of course depends on the user of your app to move around. However, assuming everybody in your workforce commutes to/from work with their iPhone then you would have two opportunities each day for the app to run in the background. A app run due to a location change can be made to execute in the background for more than 30 seconds.
voip pushes: Unlike a regular push notification, a voip push will launch the app even if the user has force terminated it. To make use of this functionality is only a tiny bit more effort than using regular push, you don't have to do anything regarding making or receiving an actual voip call, you just need the voip capability and voip certificates instead of normal push certificates.
The comment in that link is not correct regarding force quitting and background fetch - a user force quitting an app does not make it ineligible to run for a background fetch, I have force quit my own app that uses background fetch but it will still be started by the OS, however what will happen is that the frequency when the app is run will decrease lots, and if the user never runs the app again then the OS will stop launching it.
A user force quitting an app will prevent other things from happening, such as it running in the background in response to a silent push notification for example (unless its a voip push).
Also the 30 seconds in not related to download times, NSURLConnection would stop after 30 seconds, NSURLSession is designed to continue to download on your app's behalf. But if you are downloading and then applying lengthy SQL processing it would be an issue. But minutes of processing time seems excessive, are you sure its all optimized?
The goal is to be able to retrieve data from our servers periodically when app is suspended/not running
The only reliable way to achieve such a behaviour is implementing a User-facing Remote (Push) Notifications framework on backend & apps.
You can append 4kB (or 5 for VOIP) worth of data in the push JSON payload, eliminating need for a network fetch request if implemented in a handshake mechanism.
You can evaluate usage on Silent Remote Notifications to augment content updation & fetch small amounts of content opportunistically, though it has the same as Background App Refresh.
You can definitely improve the API that can take minutes due to long running SQL
And remember you need to have the app updated only when the user actually fires it up. Evaluate implementing a catchy & smooth fetching content screen that transitions into the actual screens once all data is fetched.
My application should be monitoring battery status and send messages via e-mail when certain battery charge 25%. However, I can not get it to work in the background because it doesn't fit the requirements to run in the background. Should the application monitor battery status if the user is multitasking? Or should the application stop so it won't run?
I am sure that can to do it because in this application it works but it is unclear how:
Application that works
Dataman does not check data usage continuously. It checks for differences every time you open the app.
If you are not planning to make a jailbroken app, you will not be able to do what you want to do. Your app will be suspended by iOS unless you use one of the allowed Background Modes.
Note: If you declare a background mode and you don't actually use it for it's purpose, your app will be rejected.
I'm spec-ing an iOS app (which will be built outside of our company) which will upload a user's data entry to a server. If the device is not connected to the Internet, we'd like to save data on the device and upload it when the network is re-connected. (The app will primarily run on iPod Touch devices that will be disconnected most of the time).
If the user unlocks the device and re-opens our app after the network is reconnected, then uploading to the server should be easy because the app is running.
But what if the app is not running, where "not running" can mean one or more of:
device was power cycled
user has locked the device and it's sitting in his pocket
app crashed
user exited the app
user started using other apps so our app isn't running in the foreground anymore
are there other cases?
In the cases above, is there a way (ideally a battery-efficient way) to ensure that local data is uploaded soon after Internet connectivity is restored? Is the answer different depending on which of the cases above caused the app not to be running?
And is there a minimum iOS version the device will need in order to enable some (or all) of the above not-running cases to still upload when the app is not running?
My apologies if these are obvious newbie questions-- I'm not an iOS expert.
There is an interesting technique that is used by among others Instapaper and News.me(the pioneers of this technique) where you use region monitoring to initiate background downloads or uploads. Marco (Instapaper) blogged and talked (in episode 80 of the Build and Analyze podcast) about his communication with Apple so it should be a allowed in the App Store.
In brief the technique is that you set up certain regions (geofences) like "home" or "work" and respond to the locationManager:didEnterRegion: (and similar) callback(s). Your app will wake up from the background once you enter the pre-specified region and you can check to see if there is any data to upload.
This technique won't guarantee that the data is uploaded when the network reconnects but it will allow your app to automatically upload the information when the iPod Touch users gets home to their WiFi network.
That should most likely be at least once a day which may or may not be frequent enough for you. You could add a timestamp to when the initial upload was attempted and send that along the upload once it succeeds to get the correct order of events (data entries) on your server.
There is no way to ensure this. If your application is "not running" (by the definition described in your question), it will not be capable of responding to a change in the device's network status. It should be setup to resume upload operations the next time the application runs again.
EDIT:
Some of the cases you've described may indeed provide different opportunities for your application. Specifically, if the user "exits" the app by pressing the home button or launches another app in the foreground, your application may continue to run the in the background and could potentially respond to a change in network reachability.
The nature of what may be done in the background and for how-long is well documented, and supported by any version of iOS that supports multi-tasking. I recommend you review the documentation pertaining to App States and Background Services.
device was power cycled --> really NO WAY of resuming, unless you open the App!!!
user has locked the device and it's sitting in his pocket --> apps applicationStatus is UIApplicationStateInactive but it is running in the background. You still are able to react to notifications and i.e. accelerometer events. Try the Reachability Class and Log the changes!
app crashed --> NO WAY, unless opening the App
user exited the app --> App is sitting in the background. There you have a maximum of 10 Minutes Restriction of fully using your App (like the App "Pastebot" does)
user started using other apps so our app isn't running in the
foreground anymore --> Same as user exited the app
On multitasking Apple says the following:
Real multitasking only for certain kinds of usage, as there is Audio Background playing, VOIP (like Skype), navigation applications
All the other apps can request a specific amount of time after the app is closed/in the background, to finish certain tasks (as sending an email, sms or uploading/downloading important data)
Important Quote from dev docs:
Your app delegate’s applicationDidEnterBackground: method has approximately 5 seconds to finish any tasks and return. In practice, this method should return as quickly as possible. If the method does not return before time runs out, your app is killed and purged from memory. If you still need more time to perform tasks, call the beginBackgroundTaskWithExpirationHandler: method to request background execution time and then start any long-running tasks in a secondary thread. Regardless of whether you start any background tasks, the applicationDidEnterBackground: method must still exit within 5 seconds.
If you're building a restful API then I would recommend using RestKit, it has a request queue that checks the network status on the device and starts uploading once network access has been assured. You can read more about this here: http://mobile.tutsplus.com/tutorials/iphone/advanced-restkit-development_iphone-sdk/. Read the sections about Request Queue and background download/upload. It should be noted that RestKit is a big library which has it's advantages and disadvantages. I'm not completely sure how this que works with the app lifecycle, if it saves the request que even if the app is terminated. You would have to investigate that. RestKit does support background uploading/downloading, but as already noted, I think it's impossible to do any uploading if the app is terminated and not in background state.
I wouldn't recommend using RestKit if the API isn't Rest though.
You can download and experiment with RestKit here: https://github.com/RestKit/RestKit.
I am using core location framework inside my application and I set the location string in UIBackgroundMode or Required background modes(in Xcode 4.2) for getting the updated location from didUpdateToLocation method when app is running in background and also sending this updated location to server by hitting the specific link inside didUpdateToLocation method of core location framework.
My question is that will the app be terminated after some time when running in background or not?
No, there is no specific time defined for this.But app will definitely terminate based upon certain parameter - battery drain, memory footprint issue etc.
In developer documentation it is clearly mentioned - "The system keeps suspended apps in memory for as long as possible, removing them only when the amount of free memory gets low. Remaining in memory means that subsequent launches of your app are much faster."
Go through this for complete details -
http://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html
I am sure it is not useful for the author because the question was asked in June 2012 and I am giving an answer in June 2019. This answer maybe is useful for other users.
I am posting this answer because Everyone is said that it is OS default behaviour, We can not change it....bla....bla.
Recently, I was working with the same requirement. After 2-3 week hard
work, I did it. For other users, I create a helper class for it. My
app will never be killed by OS until the location tracking enabled.
You can also verify that OS will never kill this app tracking app
Use HSLocationManager for infinite location tracking in the active and inactive state.
Refer my app which is available in the app store(App will never kill by OS if location tracking is enabled)
Location manager that allows getting background location updates every
n seconds with desired location accuracy.
Advantage:
OS will never kill our app if the location manager is currently
running.
Give periodically location update when it required(range is between 2 -
170 seconds (limited by max allowed background task time))
Customizable location accuracy and time period.
Low memory consumption(Singleton class)
iOS app may get terminated due to following reasons:
Watchdog Timeout
As you’re probably aware, since iOS 4.x, most of the time when you
quit an iOS app, the app isn’t terminated – instead, it’s sent to
the background.
However, there are times when the OS will terminate your app and
generate a crash log if the app didn’t respond fast enough. These
events correspond with the implementation of the following
UIApplicationDelegate methods:
- application:didFinishLaunchingWithOptions:
- applicationWillResignActive:
- applicationDidEnterBackground:
- applicationWillEnterForeground:
- applicationDidBecomeActive:
- applicationWillTerminate:
In all of the above methods, the app gets a limited amount of time
to finish its processing. If the app takes too long, the OS will
terminate the app.
User Force-Quit
iOS 4.x supports multitasking. If an app blocks the UI and stops
responding, the user can double-tap the Home button from the Home
screen and terminate the app.
Note: You may have noticed that when you double-tap the Home button,
you also get a list of all the applications you’ve run in the past.
Those apps are not necessarily running, nor are they necessarily
suspended.
Usually an app gets about 10 minutes to stay in the background once
the user hits the Home button, and then it gets terminated
automatically by the OS. So the list of apps that you see by
double-tapping the Home button is only a list of past app runs.
Low Memory Termination
When subclassing UIViewController, you may have noticed the
didReceiveMemoryWarning method.
Any app that is running in the foreground has the highest priority in
terms of accessing and using memory. However, that does not mean the
app gets all the available memory on the device – each app gets a
portion of the available memory.
When total memory consumption hits a certain level, the OS sends out a
UIApplicationDidReceiveMemoryWarningNotification notification. At the
same time, didReceiveMemoryWarning is invoked for the app.
At this point, so that your app continues to run properly, the OS
begins terminating apps in the background to free some memory. Once
all background apps are terminated, if your app still needs more
memory, the OS terminates your app.
I have seen that the background location updates will work for several hours. But if I go to a place without reception the device will stop to send GPS updates it wont start when I go to a place with reception. This occurs after approximately 30min.
But if I add this, in iOS6, the app won't terminate
[locationManager setPausesLocationUpdatesAutomatically:NO];
Quick answer is pretty much no. Read below though for in depth.
Since multitasking has been enabled on iOS devices that a)your app gets allocated amount of memory and b)the device limits the amount of tasks, that is applications using memory, that occur at any given time. If you take an iOS device and open several apps you'll begin to notice that the app you opened first may have been terminated and reload from the viewDidLoad.
Generally it's safe to say if your app is a recently opened app (or even on a phone where someone clears the multitasking menu often) that the device will not terminate your application in the background.