Keep timers running in background Apps without location services - iphone

Is there a way to keep timers running when an App enters background mode without location services running?
If I have a timer running in the App with location services on and enter the background then it keeps running. However calling stopUpdatingLocation also stops the timer. I would like the timer to be able to call startUpdatingLocation at some point in the furture but as it not being run it can't do this.
Any information on how multi-tasking works with location services would be helpful.

You should probably figure out when (at what time) the timer would call startUpdatingLocation and add a UILocalNotification at that time.

Related

Flutter - Timer pauses unintentionally

I have implemented a Timer as detailed in the article below, so that the timer will keep running when i change tabs.
How to implement persistent stopwatch in Flutter?
I have an issue where the Timer "loses" or pauses time, only when not plugged into my computer. When i plug it into my computer, no issues, the emulator runs fine too. I test the flutter timer against a timer on my computer or phone, and after 5mins, they match. But when my phone (Galaxy S9) isn't plugged in, after 5mins of real time, the flutter timer might only be up to 2mins, when i go back into the app the timer is running but the timer wont be what it should be. It doesn't crash or reset, its counting when i get back into the app. I'm finding it hard to debug as when I plug the phone into my computer it seems to work fine! Any ideas?
I had issues with this as well. Things working correctly when running on the Simulator is fools gold. The Timer won't run in the background like you want it to unless you do specific work to keep it running. Here is the official page from Flutter on doing work in the background: https://flutter.dev/docs/development/packages-and-plugins/background-processes
I'll suggest implementing didChangeAppLifecycleState method of the WidgetsBindingObserver and detect when the app goes to the background and when it's back in the foreground. At the point where the app goes into the background, you save the current time e.g (onPauseTime) (you can use SharedPreferences here) and the Duration left on the timer (timerDurationLeft).
When the app is back in the foreground you check if the timer was running before the app entered the background state, if it was, you then check the current time e.g (onResumeTime) and calculate the time difference in seconds (onResumeTime - onPauseTime), using the time difference and the timerDurationLeft you can calculate how much time the timer has left to run and you start/resume the timer from that point or end/set the timer to 0:00 if time has already passed.
P:S Using a background service would be the way to go if you intend to perform some actions in the middle, like set notifications at some point where the timer is almost complete.

CLLocationManager stops in background

I have an app which uses CLLocationManager to track the user's route, drawing dots along the path taken. The app runs in the background using Required background modes > App registers for location updates.
As I understand, anything that happens in the background needs to be called from locationManager:didUpdateToLocation:fromLocation as this is the method that gets called with each location update.
The problem I'm having is that sometimes this stops getting called. It seems to happen when the user's location does not change much within the space of maybe 15 minutes or so. As far as I can tell, calls to locationManager:didUpdateToLocation:fromLocation just stop, presumably to save the battery. Unfortunately, it doesn't resume again when you're back on the move.
I presume there's no way to override this behaviour, so I would like to use Notification Centre to inform the user that the app is no longer recording the route. The problem is, how can the app know that this has happened? If locationManager:didUpdateToLocation:fromLocation is not called, I can't fire my notification. If it is being called, the notification should not fire.
I don't think that there is any way to be notified that the location manager has stopped sending you events, but there is a way to prevent it from happening. In iOS 6, a new feature was added that allows the location manager to power down services if it doesn't think they are being used. If you do the following, the location manager will continue sending you events in the background until you run out of battery:
if ([self.locationManager respondsToSelector:#selector(pausesLocationUpdatesAutomatically)])
{
self.locationManager.pausesLocationUpdatesAutomatically = NO;
}
Also, in iOS6, you should be using locationManager:didUpdateLocations: as locationManager:didUpdateToLocation:fromLocation: is deprecated.
The 2 delegate methods:
-(void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager
and
-(void)locationManagerDidResumeLocationUpdates:(CLLocationManager *)manager
tells you when the location updates stop and start due to pausing.

CLLocationManager sometimes stops updating while app is in background

I have an app which uses CLLocationManager to track the user's route, drawing dots along the path taken. The app runs in the background using Required background modes > App registers for location updates.
As I understand, anything that happens in the background needs to be called from locationManager:didUpdateToLocation:fromLocation as this is the method that gets called with each location update.
The problem I'm having is that sometimes this stops getting called. It seems to happen when the user's location does not change much within the space of maybe 15 minutes or so. As far as I can tell, calls to locationManager:didUpdateToLocation:fromLocation just stop, presumably to save the battery. Unfortunately, it doesn't resume again when you're back on the move.
I presume there's no way to override this behaviour, so I would like to use Notification Centre to inform the user that the app is no longer recording the route. The problem is, how can the app know that this has happened? If locationManager:didUpdateToLocation:fromLocation is not called, I can't fire my notification. If it is being called, the notification should not fire.
Is there some kind of system notification that says location updates will cease?
I'm finding it quite hard to debug this as I can't take my Mac everywhere when I'm out and about testing the location on the device (there's only so much you can do in the simulator). Any tips for debugging would also be much appreciated!
If you haven't found the answer, I think it is because of a new attribute added to CLLocationManager called pausesLocationUpdatesAutomatically. The attribute defaults to YES, and its behaviour is exactly as you describe. Try setting it to NO and I think it will fix your problem.
Starting in iOS9, make sure you're also setting this property on your location manager:
[locationManager setAllowsBackgroundLocationUpdates:YES]
There's a delegate for location update did Fail
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
There are a few kinds of errors: kCLErrorDenied kCLErrorNetwork Add code here to handle them in the delegate method above not updating location, perhaps a UIAlertView to tell the user.
Personally, I call [locationManager stopUpdatingLocation]; on any error then restart it with an error message depending on the reason for the failure.
ALSO re background, check code in your appDelegate:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[self saveContext];
if ([CLLocationManager significantLocationChangeMonitoringAvailable]) {
// Stop normal location updates and start significant location change updates for battery efficiency.
[self.locationHandler.locationManager stopUpdatingLocation];
[self.locationHandler.locationManager startMonitoringSignificantLocationChanges];
}
else {
NSLog(#"Significant location change monitoring is not available.");
}
}
LASTLY re: testing. You can simulate some errors in location by changing the location movement in the simulator. For example, going from running to driving will cause an error. Going from running to a single specific custom location will cause an error. They should all appear in the delegate method for locationManager above.
I've managed to solve the problem by adding a local notification that fires with a 90 second delay every time a new location is added to the route. When the next location is added, the previous notification is cancelled and a new one is scheduled. This way, if it stops updating, a notification is received by the user (albeit with a 90 second delay). It's not ideal, and it may not be great for battery life, but it is a solution and it's the best I've got for the time being.
#Ron, I meet the same problem as beev describe, and i had already set pausesLocationUpdatesAutomatically to NO. I think because iOS will kill some apps that didn't be triggered in 10 minutes when it's under background. So add local notification maybe a good choice at the moment.

iPhone - Start / Stop CLLocationManager

This really leads off from my "brainstorm" last night here:
iPhone Brainstorm - CLLocation in Background - Polling every 15 minutes
When my application is active I can stop the CLLocationManager after I get a correct reading. Then after the performSelector afterDelay I can start it again, take a reading and stop it.
If though the application is but to the background when I have a timer running it never restart the CLLocationManager. I have registered for background location updates and if I do not stop the CLLocationManager it is fine but for battery I was hoping I could keep start/stopping it.
Please advise.
Thanks
James
Save the current time when the application enters the background.
When it becomes active again:
If > 15 minutes has passed since the application entered the background - start CLLocationServices
If < 15 minutes has passed, start at timer with the remaining time until CLLocationServices needs to start.
Read the Apple documentation on Location in background.
Timmers can't be used in the background.
If you keep CLLocationManager running with the correct settings it will only call location update on major change, which is when the user moves between cell towers/wi-fi points.

Is it possible to run a task periodically in Background - iOS 4

I want to poll the location from GPS in the background. So we used a NSTimer and performed periodic checks in the timer tick. In other words, can we schedule NSTimer while the app is in Background?
Thanks in advance
You can't periodically execute arbitrary code, but you can get pinged on significant location changes via startMonitoringSignificantLocationChanges in CLLocationManager.