set a timer in ios - ios

I've an app which run in background, and I want to stop all location services 30 min after entering into background mode.
So in my background function, I do this :
// 1800 sec = 30 min * 60 sec.
NSDate *date30min = [[NSDate alloc] initWithTimeIntervalSinceNow:1800.0];
NSLog(#"Date30min : %#", date30min);
self.timer = [[NSTimer alloc] initWithFireDate:date30min interval:1 target:self selector:#selector(stopLocation) userInfo:nil repeats:NO];
And my stopLocation function is :
- (void)stopLocation
{
NSLog(#"[My APP] [PASS INTO stopLocation]");
[self.locationManager stopMonitoringSignificantLocationChanges];
[self.locationManager stopUpdatingLocation];
[self.locationManager stopUpdatingHeading];
}
But my timer never call the function, what's my error please ?
(My function is correctly implement into my .h and .m file, I tested this out of the background function.
Please help..

It's not a problem with forgetting to add your timer to a run loop (in this case).
NSTimer objects don't fire when your app goes into the background. So, I would use another technique if you want to do something 30 minutes after backgrounding.
For example, use a Background Task to run your stopLocation method later:
- (void)applicationDidEnterBackground:(UIApplication *)application {
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
NSLog(#" expiration handler!");
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 30 * 60 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
[self stopLocation];
// we're done with this task now
[application endBackgroundTask: bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
Of course, you also need to have declared this:
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
in your Info.plist file, but I assume you already figured that out.

Related

Background task stops after 3 minutes

I want to run a background task. for check the network connectivity even the application in background
-(void) beginBackgroundUploadTask
{
isBackGroundRunning = YES;
if(self.backgroundTask != UIBackgroundTaskInvalid)
{
[self endBackgroundUploadTask];
}
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"Background Time Remaining :%f",[[UIApplication sharedApplication] backgroundTimeRemaining]);
}];
}
-(void) endBackgroundUploadTask
{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask ];
self. backgroundTask = UIBackgroundTaskInvalid;
}
-(void) initializeUpdateTimer
{
a= 0;
[self.updateTimer invalidate];
self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(checkNetWorkStatus)
userInfo:nil repeats:YES];
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[[NSRunLoop currentRunLoop] addTimer:self.updateTimer forMode:NSDefaultRunLoopMode]; //NSDefaultRunLoopMode
[[NSRunLoop currentRunLoop] run];
});
}
}];
}
I am initializeUpdateTimer function when application comes to background.
The task is automatomatically stops after 3 minutes.
Is it possible to extend the time for 30 minutes.
Theres no way to check if Internet is available once your app is suspended, usually iOS suspends apps in 3 mins but it depends on the OS. But theres a hacky way
If you need to know that, is your app is awake or not try using silent push notification,
if you receive silent push set a local notification for 30 or more and if you receive another silent push notification remove local notification from its schedule,
if silent push never arrives let the local notification do its job.
its my way to implement your requirement but its never recommended, neither by me.

Background fetch after a long time interval in iOS

The default background fetch interval is 3 min in iOS 7 or later but I want to background fetch after a 2 hours for news update.
I tried too many methods like i.e.
Use the NSTimer
Sleep the thread
Set minimum background fetch internal
After all hard work the result is
After Some time application crash
After Some time when application come in foreground then news update
After Some time no new data update
I have tried this code:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
__block UIBackgroundTaskIdentifier taskID=[[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"background task expiration handler called");
NSLog(#"Task ID is:%lu",(unsigned long)taskID);
[[UIApplication sharedApplication]endBackgroundTask:taskID];
}];
if(taskID==UIBackgroundTaskInvalid)
{
NSLog(#"Failed to start background task");
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"Start Background task with %f seconds remaining",[[UIApplication sharedApplication]backgroundTimeRemaining ]);
[self download];
[NSThread sleepForTimeInterval:25];
NSLog(#"Finishing Background task with %f seconds remaining",[[UIApplication sharedApplication]backgroundTimeRemaining ]);
[[UIApplication sharedApplication]endBackgroundTask:taskID];
});
}
-(void)download
{
ViewController *viewController = (ViewController *)self.window.rootViewController;
NSDate *fetchStart=[NSDate date];
[viewController fetchNewDataWithCompletionHandler:^(UIBackgroundFetchResult result) {
viewController.i++;
if(viewController.i<5)
{
[self download];
}
NSLog(#"%lu",(unsigned long)result);
}];
NSDate *fetchEnd = [NSDate date];
NSTimeInterval timeElapsed = [fetchEnd timeIntervalSinceDate:fetchStart];
NSLog(#"Background Fetch Duration: %f seconds", timeElapsed);
}
I used the recursion to update five news channels. My device not
connected to X-Code. My background fetch is on in capabilities.

How to remain getting the location continuously in the background in ios8?

How to remain getting the location continuously in the background in iOS8 and you must try your best to save electricity? Can anybody give me some advice?
In your project setting, Select Target and go to Capabilities, turn ON the background mode and tick the location updates and background fetch.
This will add background mode in your project plist.
Now, to get continuous location updates even in background, add this code in AppDelegate's applicationDidEnterBackground: method. This code will kill the background task every time and restart it. So, even when app is in background, you'll receive background location updates.
- (void)applicationDidEnterBackground:(UIApplication *)application {
if ([[UIDevice currentDevice] respondsToSelector:#selector(isMultitaskingSupported)]) { //Check if our iOS version supports multitasking I.E iOS 4
if ([[UIDevice currentDevice] isMultitaskingSupported]) { //Check if device supports mulitasking
UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance
__block UIBackgroundTaskIdentifier background_task; //Create a task object
background_task = [application beginBackgroundTaskWithExpirationHandler: ^{
[application endBackgroundTask:background_task]; //Tell the system that we are done with the tasks
background_task = UIBackgroundTaskInvalid; //Set the task to be invalid
//System will be shutting down the app at any point in time now
}];
}
}
}
Now to extend device battery life, you can use locationManager:didUpdateLocations: method as it is only called when location changes according to desired accuracy.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations lastObject];
if (location != nil) {
strLatitude = [NSString stringWithFormat:#"%f", location.coordinate.latitude];
strLongitude = [NSString stringWithFormat:#"%f", location.coordinate.longitude];
}
}
Found some Solution here
Study the example from Ray Wenderlich. The sample code works perfectly.
You can add timer to it by using this code snippet this may reduce battery consumption a bit :
-(void)applicationDidEnterBackground {
[self.locationManager stopUpdatingLocation];
UIApplication* app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
self.timer = [NSTimer scheduledTimerWithTimeInterval:intervalBackgroundUpdate
target:self.locationManager
selector:#selector(startUpdatingLocation)
userInfo:nil
repeats:YES];
}

MKDirections calculate directions when app is in the background

I want to calculate directions to a destination when my app is in the background every time it receives a location update.
However, the [MKDirections calculateDirectionsWithCompletionHandler] is an asynchronous call, and my question is therefore: will my app be terminated if this takes more than 5 seconds to complete after my app has received a location update? What would be your recommendations to make sure this request has enough time to finish?
In order to request extra time for your app to run in the background to complete its tasks (asynchronous or not), you can use beginBackgroundTaskWithExpirationHandler:.
For example:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// If the application is in the background...
if([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive) {
// Create the beginBackgroundTaskWithExpirationHandler
// which will execute once your task is complete
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:application forKey:#"application"];
// Start a timer to keep the program alive for 180 seconds max
// (less if that's all that's necessary)
[NSTimer scheduledTimerWithTimeInterval:180 target:self selector:#selector(delayMethod:) userInfo:nil repeats:NO];
});
}
// ... the rest of your didUpdateToLocation: code ...
}
- (void)delayMethod:(NSTimer*)timer {
// End the background task you created with beginBackgroundTaskWithExpirationHandler
[[[timer userInfo] objectForKey:#"application"] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}

Running Background Service in iOS

I am a new bee in iOS apps development. I want to create a background service in iOS. I also want to mention a particular time of the day and interval (every 2 hours) to call the service (kind of an Alarm to invoke service). When the service runs, some task should get performed independent of the state of app i.e. app can be in active or inactive state. Any example of it or a code snippet of implementation will help me implement this functionality.
Use this Code
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[Timer invalidate];
Timer = nil;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"Background process is Start(EnterBackground)!");
__block UIBackgroundTaskIdentifier bgTask ;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
Timer = [NSTimer scheduledTimerWithTimeInterval:120.0f target:self selector:#selector(process) userInfo:nil repeats:YES];
}

Resources