I want to upload the location in background every 30secs to 1min. Is it possible?
I have found that I can set UIApplicationBackgroundFetchIntervalMinimum. But I looked around this constant to tell the device to fetch about every 30mins. Any way to do that? Thanks.
I don't know the exact purpose of yours for uploading location for every 30 secs. It's not recommended to do so. I think you can go for MonitoringSignificationChanges in CoreLocation framework. It will give you update whenever there is a significant change in location. It helps in saving the battery.
Starts the generation of updates based on significant location changes by the following method:
func startMonitoringSignificantLocationChanges()
This method initiates the delivery of location events asynchronously, returning shortly after you call it. Location events are delivered to your delegate’s locationManager(_:didUpdateLocations:) method. The first event to be delivered is usually the most recently cached location event (if any) but may be a newer event in some circumstances. Obtaining a current location fix may take several additional seconds, so be sure to check the time stamps on the location events in your delegate method.
Fore more info: Apple Docs
Your approach has multiple problems. Most apps are not allowed to run continuously in the background like you want to do. You get ~3 minutes of background time, and then your app gets suspended. Navigation apps are an exception. If your app is a navigation app you are allowed to run continuously in the background.
Polling the GPS every 30 seconds is also a bad idea unless you're a navigation app. You'll quickly drain the user's battery.
Likewise uploading the user's location every 30 seconds will keep the cellular/WiFi radio on the phone powered up nearly constantly, which will drain the user's battery quite rapidly.
Related
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
I've got a concept of adding feature to my app which will register user location in interval of few seconds. Then sending this coordinates through cellular or Wi-Fi all when staying active in background. I need to send this in almost real time, so the app can't be killed in backgorund.
I know this concept is very power consuming but it is only a conception.
The conception of getting constant location in backgorund is in this theard https://forums.developer.apple.com/thread/69152
so I think it is possible.
But refreshing only the process in my app of sending coordinates to server it's a little bit difficult. I could not get straight answer that it is possible to set the time interval in which the app will refresh in backgrund.
Is there a method for telling the app how often it should refresh in background?
Apple won't let your app idea onto the app store. They're quite strict about which types of apps are allowed to run in the background, and are allowed to use continuous GPS. (Both of those things really drain the user's battery.) Sending a continuous stream of location updates to a server will also keep the cellular/WiFi transmitter powered up, making things even worse.
For your own experimentation, though, you can probably set up your app to be a navigation app. Those are allowed to keep the GPS "lit" constantly and to run in the background. You could then set up the location manager with the highest accuracy setting and start updating your location.
I don't think you have the ability to control how often you get location updates though. You could create a timer that fires on a regular interval and fetches the current location from the location manager. However I don't think there's much value in that, since you WILL get called when the user's location changes, and fetching the current location more often will just give you the same answers repeatedly.
My iOS app (which targets iOS 8.1+) use location services to determine if a user has entered a particular region during an event. Ideally I would like to enable the geofencing a little before the event and turn it off a little after the event completes. The problem is there is no guarantee the app is running an hour before the event so I turn on geofencing at the point the user registers for the event. This is not the best approach as it means the geofencing is on for much longer than it needs to be.
As far as I can tell, there is no way to "wake up" the app in the background at a scheduled time in iOS. I could use the push notification meant for updating content, but It's not clear to me if Apple would reject such a misuse of that notification.
Any suggestions?
I've been looking into this myself.
If you can arrange a push notification from your backend ("Silent push notification", aka "content-available"), it seems to be a good option. In real-world situations, this seems to give you the best control over the timing. Unfortunately, it won't work if the person doesn't have connectivity. Also, unfortunately, you need a backend that can queue events at a time (not just in response to an input.) If you have such a backend already, and your app is only useful to the user when they have network coverage anyway, this is probably the best option. It seems this an appropriate use of the technology, so Apple should approve.
Another option I'm trying is to use background fetch. You specify a "minimum interval" to avoid too much fetching. Try 50% of the remaining time-to-event as a minimum. Every time the app wakes up (whether in the foreground because the user opened it, or in the background because background-fetch opens it) you can calculate the time-to-next-event, update the fetch interval, or start the region monitoring. You are supposed to use "background fetch" to fetch information from a server, but there doesn't seem to be any requirement to poll a server, you could poll your internal data instead. I haven't fully tested this yet but it seems promising.
You can use significant location change monitoring, which I've read will wake up your app briefly every 15 minutes or less, and you can use the time/location information to decide whether to turn on the geofence. I think this would work well in combination with the above "background fetch": Many hours or days before the event you rely on background fetch, which you then use to turn on significant location change monitoring a few hours before the event. (There's speculation that geofencing is actually more battery efficient than significant change monitoring, but you could choose to assume that other apps on the user's device will already by watching for significant changes, in which case the marginal cost of your app adding itself to the list should be minimal.)
Putting them all together, you could create a sequence of
background fetch -> significant location monitoring -> geofencing
as the time gets closer.
There is also the CLVisit monitoring functionality, it's not understood very well, but supposedly uses less power and is called less frequently than significant location change monitoring. If the background fetch or silent remote notifications aren't working to wake up your app, give this a try, and please report back!
You can't (yet) do a silent content-available local notification (AFAICT). However, perhaps you can schedule up a local notification "Your event starts tomorrow" or something that convinces the user to click the option that starts the geofence. Here's a tutorial on it http://www.appcoda.com/local-notifications-ios8/, the response of action can be UIUserNotificationActivationMode.Background so your geofence can come on (if the user responds to the notification) without bringing the app to the foreground.
It's been 5 to 6 weeks since you asked, do you have your own answer already? Please let me know.
Both on the simulator and the device, my delegate for LocationManager is getting didUpdateToLocation:fromLocation: exactly every 5 minutes while traveling while monitoring SLC. Why is this?
According to the CLLocationManager Class Reference:
For applications that do not need a regular stream of location events,
consider using the startMonitoringSignificantLocationChanges method to
start the delivery of events instead. This method is more appropriate
for the majority of applications that just need an initial user
location fix and need updates only when the user moves a significant
distance. This interface delivers new events only when it detects
changes to the device’s associated cell towers, resulting in less
frequent updates and significantly lower power usage.
My guess is that when your app is running in the background, iOS only "wakes" the app every 5 minutes to check whether you have made a Significant Location Change, in order to conserve battery life
There might be some useful information for you also in this previous question.
I have a location-based iOS 4 app that relies on significant location change monitoring while in the background. Apple's docs state:
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.
Does anyone know how long "a small amount of time is?" Specifically, I'm wondering if I have enough time to call startUpdatingLocation on a location manager in order to get a more accurate fix than what might be provided by the initial location event. (My background location events almost always report their horizontalAccuracy as 1000m.)
If Apple's "small amount of time" would be insufficient for that purpose, am I allowed to call beginBackgroundTaskWithExpirationHandler: from a backgrounded application in order to request more time? I know that usually gives you an additional 600s, which is more than adequate.
Do you absolutely need to find a more accurate fix during application re-launch, or can you do this heavy lifting after your app has been moved into the foreground, and show a "Loading..." type screen while the work happens? That would eliminate any concerns regarding timeouts.