Code still running in background even after backgroundTimeRemaining is zero? - ios

UIApplication *application = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier background_task = 0;
background_task = [application beginBackgroundTaskWithExpirationHandler: ^{
[application endBackgroundTask:background_task];
}];
SEL selector = NSSelectorFromString(action);
timer = [NSTimer scheduledTimerWithTimeInterval:floatUpdateInterval target:self selector:selector userInfo:nil repeats:YES];
The above code (timer) is still running even after the backgroundTimeRemaining is 0 (zero).
How could this be? Isn't there a 10 min max for the above type of approach ?
Is the above code considered "app store" safe for submission ?

You are creating a timer that is just scheduled to repeat. beginBackgroundTaskWithExpirationHandler will be called when the time is up, this is your chance to stop whatever didn't finish in time.
You should invalidate your timer in beginBackgroundTaskWithExpirationHandler.

Related

How to maintain Timer to continue running when Home button is pressed [duplicate]

I want to reduce the count down of the time. So If the user minimize app then app loading the background. How can run the timer in application background? I am using the below code. When app is minimized timer is stopped. Please help me.
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerCountDown) userInfo:nil repeats:YES];
- (void)timerCountDown
{
if(secondsLeft > 0 ) {
secondsLeft -- ;
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
}
}
I got the answer, its working perfectly.
UIBackgroundTaskIdentifier bgTask =0;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
timer = [NSTimer
scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerCountDown:)
userInfo:nil
repeats:YES];
Applications don't run in the background forever; you can't guarantee that the timer will continue when the app is closed.
In the app delegate, within applicationDidEnterBackground, save any data that allows the timer to continue when the applicationWillEnterForeground. In your particular case, invalidate the timer on backgrounding, and start it up again on it entering the foreground. With your secondsLeft, you may want to be able to calculate that via a difference in NSDates, and save the start and end dates.

NSTimer not working after reset

I have a NSTimer which should be work when app in foreground but should stop when app goes to background. but if came again to foreground timer is not working. Is there any way to do that?
inbox.m
(viewDidLoad){
myTimer = [NSTimer scheduledTimerWithTimeInterval: 0.60 target: self selector: #selector(saveSlow) userInfo: nil repeats: YES];
if([[NSUserDefaults standardUserDefaults] boolForKey:#"enterBG"]==YES)
{
[myTimer invalidate];
myTimer = nil;
}
....
}
Have you reset the bool value of enterBG after the app enter foreground? If not, even the timer is generated, it'll be invalidated again later.
Another point, you generated your timer in -viewDidLoad, generally, the view life loop only invoke it one time. The next time your app enter foreground, it won't be invoked. This might be another reason why your timer won't works again. You can try put it to -viewWillAppear: instead. You need to invoke the code snippet manually.
And a suggestion, you'd better to use the related notification to handle the timer:
UIApplicationDidEnterBackgroundNotification
UIApplicationWillEnterForegroundNotification
you cant try this code in your project
UIBackgroundTaskIdentifier bgTask = UIBackgroundTaskInvalid;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.60 target:self selector:#selector(timerMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
-(void) timerMethod{
NSLog(#"in Vijay yadav ");
}
Try to remove:
[myTimer invalidate];
myTimer = nil;
As the timer will stop working in background after 3mins. When you came to foreground, it automatically runs. By invalidating and nil, you are removing the instance of your timer. In this case you again have to intialize the timer.

How to run NSTimer in background beyond 180sec in iOS 7?

I have tried this but not working more than 180 sec in iOS 7 and Xcode 4.6.2. Please help me
UIBackgroundTaskIdentifier bgTask = UIBackgroundTaskInvalid;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:20 target:self selector:#selector(timerMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
-(void) timerMethod{
NSLog(#"in timerMethod");
}
Unless you enable one of the Background modes, it is not gonna work.
Why?
You have around 10 minutes of background execution after this the timer is stopped by ios.
The timer will not fire after app is locked (iOS7), since ios suspends the foreground app and bgTask will not get fire again.
There is some workarounds, consider to check below question:
iphone - NSTimers in background
Scheduled NSTimer when app is in background?
NSTimer on background IS working

How to make an iOS app, that perform function in the background with some interval?

I want make my iOS app, that can every 5 minutes perform a specific function. How to do it?
A function is simple, like
batter = 95; // will be calculated.. every time is differ
[UIApplication sharedApplication].applicationIconBadgeNumber = batter;
I need to make timer for it, in background
You can't do this in the background unless your app fall in one of the categories: VOIP, audio playback or location update. If you places timers they will become invalids when the application goes to the background.
have a timer declared like so in my .h file:
NSTimer *MyTimer;
#property (nonatomic, retain) NSTimer *MyTimer;
Then on the .m file, I declared it like so:
UIBackgroundTaskIdentifier BackGroundTask;
UIApplication *app = [UIApplication sharedApplication];
BackGroundTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:BackGroundTask];
}];
self.MyTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self
selector:#selector(TimerMethod) userInfo:nil repeats:YES];
Following is Timer Method that call at every 5 sec.:
-(void)TimerMethod
{
batter = 95; // will be calculated.. every time is differ
[UIApplication sharedApplication].applicationIconBadgeNumber = batter;
}

iOS Not the typical background location tracking timer issue

i'm developing a sample app that tracks the user's position in background, but i don't want to leave the location service always enabled, but something in my timer does not behave properly.
My idea was that every x minutes, the service goes on, and when it have a correct new location it is released again, now is set to 10 seconds just for testing. (Significant LocationChange did not the trick, not accurated enough)
I was searching a lot (iOS Dev center + StackOverflow) and found the "new" background location features, that allows you to run code over 10 minutes after going to background, using beginBackgroundTaskWithExpirationHandler, a few blocks, and a timer.
I set the background mode to Location and by now i think i don't need to handle the end of the background time (first i want to get a location every 15-20 seconds)
the code is working "fine" but:
The timer sometimes fires, sometimes does not.
When the timer fires, it takes a minimum of 10 minutes to do it.
Some random actions in the OS (like entering to search desktop) appears to estimulate the timer to fire (not sure of this, i don't realize how it is possible, but there it is...)
And by over the code will be another qüestion.
appdelegates's methods:
//applicationDidEnterBackground
- (void)applicationDidEnterBackground:(UIApplication *)application{
NSLog(#"to background");
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task.
_triggertimer = nil;
[self initTimer];
});
NSLog(#"backgroundTimeRemaining: %.0f", [[UIApplication sharedApplication] backgroundTimeRemaining]);}
//initTimer
- (void) initTimer{
NSLog(#"InitTimer ");
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
_triggertimer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(checkUpdates:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_triggertimer forMode:NSDefaultRunLoopMode] ;
[[NSRunLoop currentRunLoop] run];
}];}
//checkUpdates
- (void)checkUpdates:(NSTimer *)timer{
NSLog(#"CheckUpdates ");
UIApplication* app = [UIApplication sharedApplication];
if (nil == _locationManager) _locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.distanceFilter = 10;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[_locationManager startUpdatingLocation];
[_locationManager startMonitoringSignificantLocationChanges];
double remaining = app.backgroundTimeRemaining;
NSLog(#"Reminaing %f", remaining);}
I tried lots of thing to try to fix this and maybe i messed or missed something... What do you see? maybe some concept errors, i'm trying to introduce myself to the blocks and I don't domain them yet ¬¬
By the way,why all the codes i've found contains this before doing anything with beginBackgroundTaskWithExpirationHandler?
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
I thought that this is for taking that 600 seconds of background... but i'm not sure!
When your app is backgrounded the timer will no longer fire unless you have the "location" value for the UIBackgroundModes key set in the app's info.plist.
You can extend the time that you are allowed to run in the background (if you haven't set "location") using beginBackgroundTaskWithExpirationHandler but that should always be paired with the corresponding end call.
Ok, the problem was that i was calling beginBackgroundTaskWithExpirationHandler twice, one in ApplicationDidEnterBackground and another one inside initTimer...

Resources