Do iOS background limitations allow for http? - ios

I would like to run a process in the background of my application that gets the user's current latitude/longitude (at 5 minute intervals) and reports it back to our server via web service call. When I add required background modes to my info.plist I have the following options:
-App plays audio
-App registers for location updates
-App provides Voice over IP services
Now in my case I obviously need the second choice on the list, but once I have the location what can I do with it? Can I make a web service call in the background?? What other limitations might there be??
Thanks a lot!

When you App is in background mode you can not establish a HTTP connection the usual way. You have to setup a background task that sends the location updates to your server.
I found a short tutorial that covers exactly what you're looking for (I've not tested the code).
This is a summary of how it works
When your App is running in background and a location change occurs, iOS wakes up your App and calls the delegate method locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation of your CLLocationManager. When this happens, check if your App is running in the background and setup the background task if it is. The background task then should send the data to your server.
Limitations
The documentation is not clear about how much time such a background task may take to finish, but I slightly remember it was something around 10 minutes maximum.
As far as I know you can not update the UI while your App runs in the
background

Related

can we get location updates in IOS swift in a regular intervel of time even when app is not running in foreground

I want to get location updates of the user in a regular interval of time even if the app is not running in foreground.
In most of the articles i have read, they said that the OS will forcefully stop or suspend the background service the app have started.
What i need is the app should regularly check the user location and when that location becomes greater than say 10Kms the app should trigger a local notification.
We were able to do the functionality correctly when the app is ran again by the user. But it wont work in background. And if we inegrated it as a background service , then it is causing the app to crash. :(
this part caught my attention after a long time of search
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW8
As far as I understood, they say that the OS will wakeup the app to get the current location when it senses a change in location.
But I didnt get any helping tutorial to accomplish the same
These are the tutorials which I refered
Periodic iOS background location updates
How do I get a background location update every n minutes in my iOS application?
Getting user location every n minutes after app goes to background
iOS Not the typical background location tracking timer issue
iOS long-running background timer with "location" background mode
What i need is preferably a background service or something which does the job done which check of the current location calculate distance and makes a local notification.
But as far as i know all the background services will be suspended or killed by the OS within some time after the app is gone in background.
Please guys I am desperate, Its been 2 weeks i am on in its tail.
Building the same for Android was a piece of cake actually.
Any help ???
You can get background location updates easily, you need to enable "Location updates" under "Background Modes" section in capabilities.
You also need to request for Always Authorisation and finally add this
if #available(iOS 9.0, *) {
locationManager.allowsBackgroundLocationUpdates = true
}
Make sure "Location updates" is activated else the above code will lead to a crash.
Also, write the CLLocationManager Delegate Methods in your AppDelegate class as this would increases chances of those methods being called as mentioned on Raywenderlich Background Location tutorial

GPS monitoring in background mode for iOS

I want to implement a feature on iOS to notify user when reach a special location (such as a bus station, don't miss it), it is easy if user always put app in foreground mode, using GPS location to detect whether arrived nearly or not. The key point is how to achieve it in background mode.
One possible solution is to update GPS in background mode, something like map navigation APP, but as you know GPS is power killer, user may not like it.
See CoreLocation API, found the following delegate callbacks, I am not sure whether they work well in background mode. Any idea on this topic please share and discuss together and thanks in advance.
- (void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
- (void)locationManager:(CLLocationManager *)manager
didStartMonitoringForRegion:(CLRegion *)region __OSX_AVAILABLE_STARTING(__MAC_TBD,__IPHONE_5_0);
From the Location and Maps Programming Guide
In iOS, regions associated with your app are tracked at all times,
including when the app isn’t running. If a region boundary is crossed
while an app isn’t running, that app is relaunched into the background
to handle the event. Similarly, if the app is suspended when the event
occurs, it’s woken up and given a short amount of time (around 10
seconds) to handle the event. When necessary, an app can request more
background execution time using the
beginBackgroundTaskWithExpirationHandler: method of the UIApplication
class.

iOS background operations - Is it possible to perform network request subsequent to significant location updates?

I am building an app, that has location updates enabled in the background, for this I am using an instance of CLLocationManager with the following code:
self.coreLocationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.coreLocationManager startMonitoringSignificantLocationChanges];
I implemented its delegate callback - (void)locationManager:(CLLocationManager *)locationManager didUpdateLocations:(NSArray *)locations, in which I trigger a network request to Google in order to reverse geocode the coordinates and retrieve the address of the location.
This does work very well if the app is in the foreground, but in the background it it doesn't seem to work. I have difficulties debugging it for testing as well, because I can't access the logs when the app is in the background (so I used Mixpanel, an analytics framework to capture the location updates as events, but apparently they don't work either).
In order to receive significant location change updates in the background you need to restart location services when your app is launched into the background - your delegate methods won't be called unless you do this.
From the Location And Maps Programming Guide -
If you are monitoring regions or using the significant-change location
service in your app, there are situations where you must start
location services at launch time. Apps using those services can be
terminated and subsequently relaunched when new location events
arrive. Although the app itself is relaunched, location services are
not started automatically. When an app is relaunched because of a
location update, the launch options dictionary passed to your
application:willFinishLaunchingWithOptions: or
application:didFinishLaunchingWithOptions: method contains the
UIApplicationLaunchOptionsLocationKey key. The presence of that key
signals that new location data is waiting to be delivered to your app.
To obtain that data, you must create a new CLLocationManager object
and restart the location services that you had running prior to your
app’s termination. When you restart those services, the location
manager delivers all pending location updates to its delegate.
Also, when you are launched into the background you should not perform network operations unless you request additional execution time. From the Location and Maps Programming Guide again -
Because your app is in the background, it must do minimal work and
avoid any tasks (such as querying the network) that might prevent it
from returning before the allocated time expires. If it does not, your
app will be terminated. If an iOS app needs more time to process the
location data, it can request more background execution time using the
beginBackgroundTaskWithName:expirationHandler: method of the
UIApplication class.

Why my location service is not running in background

My core location code is working fine all delegates are working properly, I can view exact location in mapview. Now I want this application to keep running in background, I searched on internet and found only few services are allowed to work in background and other suspend in few minutes. For enabling thos services I set a flag of uibackgroundmode = location and my delegate on core location is also working but still why my application suspends after running 20 minutes?
There are a few reasons why this doesn't work. First try the answer of this question:
Specify location background mode
Use an NSTimer in the background by using UIApplication:beginBackgroundTaskWithExpirationHandler:
In case n is smaller than UIApplication:backgroundTimeRemaining it does works just fine, in case n is larger, the location manager should
be enabled (and disabled) again before there is no time remaining to
avoid the background task being killed. This does work since location
is one of the three allowed types of background execution.

How to update location in background online in an iOS app?

I'm trying to build an iPhone app that requires me to keep track of the user's location at all times using Core Location. I am using startMonitoringSignificantLocationChanges so that it updates in the background and because the accuracy is not as important as it being updated whenever there is a significant change.
Currently I make an HTTP request to a web service to update the location. This works perfectly when I am running the app - my location gets updated in the MySQL database I'm storing location data in. But when the app enters into the background - I can see the location services icon in the top right corner of the phone still running, but when I go back and look at the database, it didn't update my location at all. I tested this by taking a drive across town, one way with the app running, and one way with the app in the background.
From Apple's documentation:
If you leave this service running and your application is subsequently suspended or terminated, the service automatically wakes up your application when new location data arrives. At wake-up time, your application is put into the background and given a small amount of time to process the location data. Because your application is in the background, it should do minimal work and avoid any tasks (such as querying the network) that might prevent it from returning before the allocated time expires. If it does not, your application may be terminated.
How long exactly is this "small amount of time to process location data"? And is it just not recommended to query the network, or is it not possible to query the network in that time? Is there a better way to keep track of the location of several different users even when the app is in the background?
You should have look at background tasks.
When Apple says small amount of time to process location data, you shouldn't really rely on getting any processing time after the locationManager:didUpdateToLocation:fromLocation: method has returned. Assuming that you're running the HTTP request asynchronously in a separate thread, you are likely not given enough time to finish it before your app is suspended.
UIBackgroundTasks let you ask the operating system for extra processing time while in background. Making a HTTP request could be such a task. The time limit is 10 minutes although you are not guaranteed to get this much time.
In your location callback, you should define a new background task for your request. The expiration handler block is triggered at any time if the operating system decides that it can not give you any more processing time.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// Start your request here
UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
backgroundTask = UIBackgroundTaskInvalid;
// Cancel your request here
}];
}
And when the request has finished you should tell the application that the task is done:
- (void)requestFinished:(id)request {
[[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}
In this example, I've not taken into account that you may receive multiple location callbacks before the request has finished. If that happens, you need to cancel that request and current background task before starting a new one, or create a separate background task for each request.
Another way of doing it would be to run the HTTP request synchronously on the main thread in the location callback method, but that will be a bad thing to do for multiple reasons, like locking up the interface if the user opens the app while a request is running.

Resources