how to get location updates for every n secs in ios - ios

I want to get the location updates for every 30 secs.In foreground and when the app is in background.Also how could I know that my location is updating or not if I use simulator.please provide some help.

You don't, you get location update when the device moves. Location update are not really meant to be polled, but rather you are notified when there is a new location available.
Just create a instance of CLLocationManager and start call the startUpdatingLocation method. Then the delegate of the CLLocationManager will start receiving location updates. Just be aware that if you keep this running for a long time it will drain the devices battery faster.

Related

startMonitoringSignificantLocationChanges getting triggered after traveling distance of more than 3-5km

Im working on some POC where in i want a location update even when the app is terminated, im using the startMonitoringSignificantLocationChanges, where is as per docs(Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification.) Where as in my case the location updates are not triggered exactly after 500m(it is able to trigger the background location update sometimes at 3km or 9km etc, which is not consistant). So is there any way that we can figure out that user has travelled exactly 500m or something to trigger the location update?
Is there any way that we can make the app to get the location update even on terminated state at particular distance travelled by user?
Thanks in advance.
My POC is something related to geoFencing where in after traveling user with certain distance, i would be changing the regions that user should be monitored, but in foreground/background its fine because if i use distanceFilter, i could able to have control with me to realter/rearrange the geoFencing to be observed, but it doesnt work in background, so i had to use the startMonitoringSignificantLocationChanges to have the location update even on terminated state.

Xamarin - IOS - CLLocationManager - Timer stops when phone goes to sleep

i have an application that uses the CLLocationManager in the background. It works as expected. I am trying multiple ways to optimize the battery because it needs to provide close-to-real-time location updates. I know that when the CLLocationManager is configured to work in the background, my app wakes-up everytime a location update happens.
So i was thinking about doing something like that: when a location update arrives and my event handler is called, i process the location, stop location updates and begin a timer that will start location updates again after 15 seconds.
This works pretty good as long as the phone is not sleeping or app is in background. When the phone goes to sleep, then the timer stops. Is there a way to avoid that? i was thinking that maybe as i am stopping location updates, IOS considers that the application is not allowed anymore in background so it stops all code execution, but actually i have no clue what is happening. Does anyone have a clue?
Edit: I have tested the below solution from Michal and it works like a charm. Even if the timer elapses in 15 seconds the effect on the battery are great. My app used to consume 50% of battery in a few hours. Now it doesn't even consume 5%.
This is the sequence I use:
Create a LocationManager and set it to work in the background with best accuracy
When the first gps fix arrives, set the accuracy to 3 kilometres and start a timer which elapses in 15 seconds
When the timer ticks set the accuracy back to best and upload to server all the received locations.
Take a look at this page of Apple documentation: pausesLocationUpdatesAutomatically. It describes that you can pause the location updates and then resume it. It it still doesn't solve your problem, then there's an additional note:
For apps that have in-use authorization, a pause to location updates
ends access to location changes until the app is launched again and
able to restart those updates. If you do not wish location updates to
stop entirely, consider disabling this property and changing location
accuracy to kCLLocationAccuracyThreeKilometers when your app moves to
the background. Doing so allows you to continue receiving location
updates in a power-friendly manner.
Maybe you can use this tip and do following:
1) Start with setting accuracy to your actual need (NearestTenMeters)
2) When the location update comes, process it, set the location accuracy to ThreeKilometers, then set a 15 minut timer after which you should change the accuracy back to NearestTenMeters

iOS: Location Update in Application Suspended State

Is it possible to update location when application is in suspended/terminate state.
i want to update location every 500 meters when app is in suspended/terminate state.
thanks in advance.
When terminated the only real way to get updates is to use Region Monitoring but you will only get major updates so I doubt it will work for 500 meters.
From the documentation:
If your app is terminated either by a user or by the system, the
system doesn't automatically restart your app when new location
updates arrive. A user must explicitly relaunch your app before the
delivery of location updates resumes. The only way to have your app
relaunched automatically is to use region monitoring or
significant-change location service. However, when a user disables the
Background App Refresh setting either globally or specifically for
your app, the system doesn't relaunch your app for any location
events, including significant change or region monitoring events.
Further, while Background App Refresh is off your app won't receive
significant change or region monitoring events even when it's in the
foreground.
There are good reasons for this. Firstly people don't want apps that 'snoop' on them all the time and even if there is a good reason imagine having 10 apps doing this constantly. It's going to start causing you performance and battery life issues.
EDIT
There appears to be some confusion by a lot of people over this issue so I will attempt to clear things up a bit.
Your app is NOT supposed to be continually tracking location while terminated (or suspended really). You are just not allowed to do this both for privacy reasons and so that you don't drain the battery excessively.
While your app is in the foreground you can use location services via startUpdatingLocation to monitor the device location. Assuming the app has been granted permission this will use all available hardware (GPS, WiFi, Cellular).
Now from the documentation itself:
If you start this service and your app is suspended, the system stops
the delivery of events until your app starts running again (either in
the foreground or background). If your app is terminated, the delivery
of new location events stops altogether. Therefore, if your app needs
to receive location events while in the background, it must include
the UIBackgroundModes key (with the location value) in its Info.plist
file.
So once suspended and terminated your options are really to monitor regions and to monitor for significant location changes. Neither of these are particularly accurate or frequent. One reason for this is that they only use low power methods to get the position (WiFi and Cellular) they don't use the GPS.
So no accurate and/or frequent location tracking while an app is suspended or terminated. This just has to be accepted and you need to design your apps accordingly.
let locationManager = CLLocationManager()
locationManager.startMonitoringSignificantLocationChanges()
After returning a current location fix, the receiver generates update events only when a significant change in the user’s location is detected. It does not rely on the value in the distanceFilter property to generate events
If you start this service and your app is subsequently terminated, the system automatically relaunches the app into the background if a new event arrives. In such a case, the options dictionary passed to the application(:willFinishLaunchingWithOptions:) and application(:didFinishLaunchingWithOptions:) methods of your app delegate contains the key location to indicate that your app was launched because of a location event. Upon relaunch, you must still configure a location manager object and call this method to continue receiving location events. When you restart location services, the current event is delivered to your delegate immediately. In addition, the location property of your location manager object is populated with the most recent location object even before you start location services.
Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
Hope It helps

How to know when to stop the location services?

to retrieve location of the user when the app is in the background i first do startMonitoringSignificantLocationChanges then when DidUpdateLocations is fired i do with a second CLLocationManager startUpdatingLocation to retrieve the exact geoposition (with an accuracy on 100m)
The problem is that the doc say:
Calling this method causes the location manager to obtain an initial
location fix (which may take several seconds). After that, the receiver generates update events primarily when the value in the distanceFilter property is exceeded.
So as i understand the first DidUpdateLocations will be called with a fix not really accurate, and with time other DidUpdateLocations will be called with more accurate location.
Now the problem is, when (and how?) did i need to stop the startUpdatingLocation ? i m in the background so i can't use any timer or think like this
Since you require a 100m accuracy, you can simply check the location horizontal accuracy property. If the condition is fulfilled you can stop the core location manager otherwise you keep tracking.
Be aware that usually the callback of significant monitoring changes keeps your app alive for a minimum amount of time.
At wake-up time, the app is put into the background and you are given
a small amount of time (around 10 seconds) to manually restart
location services and process the location data. (You must manually
restart location services in the background before any pending
location updates can be delivered, as described in Knowing When to
Start Location Services.) 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.

What strategy to adopt to monitor the user location in background?

I want to track the user location in background, in the purpose to show him an alert when he is close to one of his friend.
So i start with CLLocationManager. As far as i know their is only one reliable way to let the app know about the location update even if the user reboot the Iphone or kill the app: startMonitoringSignificantLocationChanges. But the problem is that even inside a city with many wifi, startMonitoringSignificantLocationChanges fire the DidUpdateLocations when the user move around 1km and that is really too much for my need
on the other way startUpdatingLocation is firing DidUpdateLocations at good interval (even too much because even when the user do not move it's fire quite often DidUpdateLocations). But startUpdatingLocation not survive to iphone reboot or app being killed by the user. Also I suspect that even with an accuracy of 100m, startUpdatingLocation use lot of battery consumption.
So the question: What strategy i can use in my app to track efficiently without draining too much the battery the user location at full time? I need an accuracy of around 100m and if possible an interval between 2.5 - 5 min for each track (i didn't find any option to specify a delay to wait before to catch a new location)
Actually i think to do something like this :
2 locationManager, 1 GPS and 1 Significant Changes
when app start I do with significantChangesLocationManager: startMonitoringSignificantLocationChanges and startMonitoringVisits
I also call GPSLocationManager startUpdatingLocation to retrieve the accurate user position. I set up PausesLocationUpdatesAutomatically(true) so that the GPSLocationManager will stop by himself soon or late
on DidUpdateLocations raise by the GPSLocationManager I start monitoring region enter/exit (100m radius around the obtained latitude/longiture) with significantChangesLocationManager
What do you think of such strategy ?
Even though you will receive more triggers than you need, as you already said, you can use startMonitoringSignificantLocationChanges. It is implemented in a very energy efficient way. It allows the app to be terminated and only be woken up again when iOS thinks the device has moved significantly. Another advantage would be that your app doesn't need the location background mode, which could raise questions during an app review.
The startUpdatingLocation let's the app continuously update the location of the device, even though you only receive a couple didUpdateLocations: events. Also, iOS cannot shutdown the app while updating is active, so it consumes a lot of battery.
You can also consider geofencing, with an exit geofence around the current location. However, significant location updates will be more reliable. Exit geofences won't trigger anymore once you're already out of a geofence, which could happen when the phone is turned off inside a geofence and turned back on outside. This solution has the same advantage of not needing a background mode.
As far as I understand your use case, startMonitoringSignificantLocationChanges sounds as the best option. You won't have control over the exact time interval and distance it triggers, but it is very energy efficient and easy to use.
As mentioned in comments, here are some approach I had to do in order to get the expected result in our app.
Significant Location Updates - is good to wake your app up once it gets finished by some reason that you can't control, so even if you lose some points, it will get back in some seconds/minutes.
This is not good if you need a good accuracy, as you cannot control the distance / time or whatever, iOS will update locations when mobile antenna is changed, wifi connection, turn air plane mode off and on but will not give a sequence of gps points.
Start Location Updates - Best accuracy but battery drainer. So you can't just turn it on let it go. You must implement some controls over it.
Background tasks - The only way I've found to keep my app alive.
The way you can combine is:
Have 2 location managers isolated, one for significant location change and one for start updating location;
Start your app with both turned on;
Inside your didUpdateLocations you can create your logic to start and stop your background tasks;
Create methods to start and pause your location manager and create your timers to control that;
inside your bg task you will start or pause your update locations, but never stop it, just if for example, your user logs out and you want to stop location;
keep significant location update location manager alive forever, if for some reason iOS decide to kill your app when in bg, it will ensure that in a given moment your app will come back to life;
For battery live, try do not use kCLLocationAccuracyBestForNavigation for accuracy as when it starts it eat a LOT of resources, most of time, kCLLocationAccuracyBest is more then enough and if you can use kCLLocationAccuracyNearestTenMeters;
Your didUpdateLocations will give you mostly a bunch of points, try to get only those with good horizontalAccuracy, around 20 meters for us was good enough, so let it work and once you have a point with good accuracy, you can pause it again.
Below you have some links that helped me a lot to implement our solution, none of those have a "as is" solution, as I said, I had to mix all of them and test a lot to understand its behaviour and make the necessary adjustments.
https://github.com/voyage11/Location
http://mobileoop.com/background-location-update-programming-for-ios-7
http://zaachi.com/2013/09/30/ios-locationmanager-location-update-in-my-own-interval-with-application-in-the-background.html
In addition to Mark's answer I would like you to explore pausesLocationUpdatesAutomatically which can help you save battery from draining when user has stopped Apple Documentation
Allowing the location manager to pause updates can improve battery life on the target device without sacrificing location data. When this property is set to true, the location manager pauses updates (and powers down the appropriate hardware) at times when the location data is unlikely to change. For example, if the user stops for food while using a navigation app, the location manager might pause updates for a period of time. You can help the determination of when to pause location updates by assigning a value to the activityType property.

Resources