I need to be able to get precise location updates continuously even if the app is terminated.
Here is my scenario:
My job is that I have to get the location updates every second whenever the user is driving on delivery routes even if the app is terminated to monitor the user's car trips and give the user a report of the trips.
I know how to get if the user is driving using CMMotionActivityManager
let motionActivityManager = CMMotionActivityManager()
motionActivityManager.startActivityUpdates(to: operationqueue,withHandler: motionActivityHandler)
I'm also familiar with starting updating location from the foreground and enabling background modes for location updates.
let locationManager = CLLocationManager()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.showsBackgroundLocationIndicator = true
locationManager.pausesLocationUpdatesAutomatically = false
locationManger.startUpdatingLocation()
But the idea is that I don't want to start the location updates from the foreground and minimize the app so that I don't waste a lot of energy, and if the user chooses to close the app from the App Switcher it will kill the app and the location updates and that's not what I need.
I'm using locationManager.startMonitoring(for: Region) because the system automatically relaunches the app into the background when the user exits or enters the region and then I check if he is driving and if that was true I start locationManger.startUpdatingLocation() but the problem here is that the app only runs for 10 seconds and even if I turned on the location updates which are allowed to work in the background the systems shuts the app down.
Also tried locationManager.startMonitoringSignificantLocationChanges() which is also like the region monitoring the system relaunches the app into the background but only when the user moves for about 500 meters and also the app won't work for enough time to monitor a full trip.
Also tried to work with SwiftBackgroundLocation library but it won't work correctly on real devices.
I need to be able to turn the location updates form the background and get location updates continuously and only when the user stops driving I stop location updates and stop the app.
Also is there is a way to get an exception from apple to work in the background like that if we applied for some kind of a special entitlement for the app (if the user installed the app then he wants to monitor his trips and of course he is told about the location updates running in the background).
Sorry for the long question.
Related
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
I require the user running location and route map path, When an application is Terminate or Background mode.
Currently I am using significant location for application kill mode, but we are not getting proper distance and route.
Because didUpdateLocations is called after some specific interval so that I am not getting proper distance.
Please guide.
According to Apple docs :
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.
This is why startMonitoringSignificantLocationChanges() would not work reliably for tracking user location change other than driving/public-transport.
Now, coming back to your problem of having to track user location when app is terminated, unfortunately you cannot track location when the app is terminated
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 the significant-change location service.
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
I have an app which uses the users location in the background and foreground. In the background when the user stops the vehicle the app automatically goes to sleep and calls stopUpdatingLocation. Everything works as expected.
Now I want to make sure the app relaunches it self when the user starts driving again. To achieve this I add a region with 200m radius with the last location just before I call stopUpdatingLocation. With the method didExitRegion I just call startUpdatingLocation again.
This gives me mixed results, it seems that sometimes the simulator works as expected but when driving around I cannot get this to work. The exitRegion works because I can receive a localNotification.
My question:
Is above possible, so is it possible to wake the app and start updating the users location in the background ?
Are there any code examples available achieving this ?
I suggest you to use startMonitoringSignificantLocationChanges and stopMonitoringSignificantLocationChanges
From Apple;
The significant location change service delivers events normally while an app is running in the foreground or background. For a terminated iOS app, this service relaunches the app to deliver events. Use of this service requires “Always” authorization from the user.
I had done loads of R&D on locations services and I come to know that if you kill app from background then there is no way you can get location update.
but now I observed even if I kill Foursqure from background it still uses location services as location icon is present on the top, Once I turn off location services for foursquare location icon gets disappeared from top.
please guide me how foursquare do this?
Apps can register to get deferred location updates. This means that the OS can accumulate location data and feed it to the app later when the program is launched. Perhaps this is what's going on with Foursquare?
From Apple docs:
In iOS 6 and later, you can defer the delivery of location data when
your app is in the background. It is recommended that you use this
feature in situations where your app could process the data later
without any problems. For example, an app that tracks the user’s
location on a hiking trail could defer updates until the user hikes a
certain distance and then process the points all at once. Deferring
updates helps save power by allowing your app to remain asleep for
longer periods of time.