I am implementing a kind of tracking app and i need to spot my location once and send it once per 10 - 20 seconds (period value is important and can't be exceeded).
To lower battery consumption i stop location updates. This works good in foreground, but how can i do it when app moved in background?
I looked info about background fetch, but it hasn't got precise time for periodic sending data
How can i perform this task?
You can start and Stop periodic location update while app is in background.
To achieve this add class from given link for Location Update.
After that import LocationTracker.h in your AppDelegate.
Add Below code in your didFinishLaunchingWithOptions.
let locationTracker : LocationTracker = LocationTracker();
locationTracker?.startLocationTracking();
In LocationTracker.m, you can set duration to restart update.Here i set 1 minute or 60 Seconds.
//Restart the locationMaanger after 1 minute
self.shareModel.timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self
selector:#selector(restartLocationUpdates)
userInfo:nil
repeats:NO];
You can also set duration time for fetch Locations. Here I fetch location for 10 Seconds.
self.shareModel.delay10Seconds = [NSTimer scheduledTimerWithTimeInterval:10 target:self
selector:#selector(stopLocationDelayBy10Seconds)
userInfo:nil
repeats:NO];
Related
I'm using an NSTimer to play an audio file every x number of seconds. The audio files are in sync with a constantly running process, so the interval of the NSTimer is the shortest it can be (to my knowledge):
self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:#selector(updateTimerFired:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.updateTimer forMode:NSRunLoopCommonModes];
My problem occurs during the transition to the background state e.g. when the user clicks the home button. It seems that a latency occurs with the timer, and the "updateTimerFired:" method isn't called as reliably during the transition. This results in the audio files playing out of sync, although they eventually sync back up after the transition is complete. Note that my app incorporates the Audio background mode.
Is there a more reliable tool other than NSTimer to ensure that the latency does not occur when transitioning to the background?
Ended up replacing the NSTimer with dispatch_source_create:
self.timerQueue = dispatch_queue_create("updateTimerQueue", nil);
self.updateTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.timerQueue);
dispatch_source_set_timer(self.updateTimer, DISPATCH_TIME_NOW, (1 * NSEC_PER_SEC) / 50, (1 * NSEC_PER_SEC) / 20);
dispatch_source_set_event_handler(self.updateTimer, ^{
[self updateTimerFired];
});
dispatch_resume(self.updateTimer);
This provides a dedicated queue for the timer to perform on, and is not interrupted by a transition to the background.
- (NSTimer *) timer
{
(!_timer)
{
_timer = [NSTimer timerWithTimeInterval:86400 target:self selector:#selector(timeset:) userInfo:nil repeats:YES];
}
return _timer;
}
You can't schedule execution for a specific time in the background on iOS. You can schedule a UILocalNotification - but your app will only be launched if the user taps on the notification.
Your best bet is to use background fetch mode. You app will be woken at intervals and given an opportunity to fetch new data. You can check to see if the time is at or after 7 and decide whether to refresh the data.
I've opted in to background location updates in an App I'm working on.
In my LocationManager class, I've got a method that looks like this:
- (void)beginUpdateTimer
{
[self.updateTimer invalidate];
self.updateTimer = [NSTimer timerWithTimeInterval:ForceUpdateDuration
target:self
selector:#selector(updateWithLastKnownLocation)
userInfo:nil
repeats:NO];
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop addTimer:_updateTimer forMode:NSRunLoopCommonModes];
}
The method -updateWithLastKnownLocation potentially calls beginUpdateTimer again.
In testing my app, I've discovered that the timer continues to fire upon the app moving in to the background, so long as I've enabled background location updates. Shouldn't this NOT be happening though? Can I rely on this?
Thanks!
Yes, you can rely on it, provided the timer was running at the time you went into the background.
I am working on a alarm application. I faced a problem from last 2 weeks. My problem is: My application is running in background.First time I install the application and set the alarm & close the app. If the alarm time is more than 3 minutes from current time then its not ringing means after 3 min alarm is not ringing in background process. If application is on then alarm is working.
This is my code:
self->bgTask = 0;
NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler: ^
{
NSLog(#"beginBackgroundTaskWithExpirat");
dispatch_async(dispatch_get_main_queue(), ^
{
NSLog(#"dispatch_async");
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}];
dispatch_async(dispatch_get_main_queue(), ^
{
NSLog(#"dispatch_get_main_queue");
//Start BG Timer
[self Start_Update_Timer];
self->bgTask = UIBackgroundTaskInvalid;
});
// This is my timer for background running ..
-(void) Start_Update_Timer
{
//If timer is already running, stop the timer
if(self.callTimer)
{
[self.callTimer invalidate];
self.callTimer=nil;
}
//call the timer for every one sec
self.callTimer =[NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(update_Alarm_List) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.callTimer forMode:NSRunLoopCommonModes];
}
Because applications are not supposed to work like this. If you want your app to continuously play sound on the background, then it should be registered as an app that does it specially. Like a music player. If your app only delivers alarms, then you have to use a local notification to "trigger" the sound from your app. The notification can be played with a 30 secs sound and replay again at certain intervals. Your app wont play after 3 minutes because your "background" execution time has expired. That is the time that apple lets your app run in the background to do whatever you have to do after the user has closed your application.
This is for the case in where you want to keep playing sound on the background. Note that if the playback stops your app will stop.
https://developer.apple.com/library/ios/qa/qa1668/_index.html#//apple_ref/doc/uid/DTS40010209
If you want to use notifications with sound (30 secs max) see here:
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/IPhoneOSClientImp.html
I have a driving application when I start the trip I have to collect location details along with date and time in hours, minutes, seconds and milliseconds for every second and accelerometer details along with date and time in hours, minutes, seconds and milliseconds for every 0.25 seconds and when the trip is stopped recording should be stopped. I have taken a timer for location details with interval 1 second
self.locationTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(locationTimerFired:)
userInfo:nil
repeats:YES];
- (void) locationTimerFired:(NSTimer *)timer
{
CLLocation *newLocation = locationManager.location;
[self updateLocation:newLocation andSpeed:newLocation.speed];
[defaultCenter postNotificationName:LocationChangedNotification
object:nil
userInfo: userInfo];
}
in the received LocationChangedNotification I am recording the location and time as mentioned for every second.
This is sometime fine when the application is in foreground but when the application is in background timer timer fires interval is not accurate it fires sometimes for 2 seconds, for 3 seconds and some times 2 times a second why this is happening?
Please suggest. Also I have registered for location updates in background mode in info.plist.
I have taken a timer for accelerometer details with interval 0.25 second as follows
self.accelTimer = [NSTimer scheduledTimerWithTimeInterval:0.25
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:YES];
Thanks.
Don't use timers. Instead, configure the location manager to give you callbacks at your desired accuracy (presumably maximum) and use the callback to save the location and speed with the current time.
Then, when you come to use / display the data you can filter / extrapolate to get the location data at your desired time interval.
The timers don't work in the background because they aren't designed to. Location callbacks are designed to...