I need to call a web service in every minute and parse the data when app is in background state.
Since the APP uses location service I have enabled background mode for update Location.
I tried calling location update by using a timer background task, but it not working.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"ending background task");
[[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
}];
self.timer = [NSTimer scheduledTimerWithTimeInterval:60
target:self.locationManager
selector:@selector(startUpdatingLocation)
userInfo:nil
repeats:YES];
}
Is there any way to implement this with less battery consumption.
I referred this link
I'm not getting which solution is better here.
AppDelegate.h
#import <UIKit/UIKit.h>
@interface AppDelegate : NSObject {
// Instance member of our background task process
UIBackgroundTaskIdentifier bgTask;
}
@end
AppDelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(@"Application entered background state.");
// bgTask is instance variable
NSAssert(self->bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
dispatch_async(dispatch_get_main_queue(), ^{
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}];
dispatch_async(dispatch_get_main_queue(), ^{
if ([application backgroundTimeRemaining] > 1.0) {
// Start background service synchronously
[[BackgroundCleanupService getInstance] run];
}
[application endBackgroundTask:self->bgTask];
self->bgTask = UIBackgroundTaskInvalid;
});
}
There are couple key lines in the above implementation:
The first is the line bgTask = [application beginBackgroundTaskWithExpirationHandler..., which requests additional time to run clean up tasks in the background.
The second is the final code block of the delegate method beginning with dispatch_async. It's basically checking whether there's time left to run an operation via the call [application backgroundTimeRemaining]
. In this example, I'm looking to run the background service once but alternatively, you can use a loop checking on the backgroundTimeRemaining on each iteration.
The line [[BackgroundCleanupService getInstance] run] will be a call to our singleton service class, which we'll build right now.
With the app delegate ready to trigger our background task, we now need a service class that will communicate with the web server. In the following example, I'm going to a post a fictitious session key and parse a JSON encoded response. Also, I'm using two helpful libraries to make the request and deserialize the returned JSON, specifically JSONKit and ASIHttpRequest.
BackgroundCleanupService.h
#import <Foundation/Foundation.h>
@interface BackgroundCleanupService : NSObject
+ (BackgroundCleanupService *)getInstance;
- (void)run;
@end
BackgroundCleanupService.m
#import "BackgroundCleanupService.h"
#import "JSONKit.h"
#import "ASIHTTPRequest.h"
@implementation BackgroundCleanupService
/*
* The singleton instance. To get an instance, use
* the getInstance function.
*/
static BackgroundCleanupService *instance = NULL;
/**
* Singleton instance.
*/
+(BackgroundCleanupService *)getInstance {
@synchronized(self) {
if (instance == NULL) {
instance = [[self alloc] init];
}
}
return instance;
}
- (void)run {
NSURL* URL = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.example.com/user/%@/endsession", @"SESSIONKEY"]];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:URL];
[request setTimeOutSeconds:20]; // 20 second timeout
// Handle request response
[request setCompletionBlock:^{
NSDictionary *responseDictionary = [[request responseData] objectFromJSONData];
// Assume service succeeded if JSON key "success" returned
if([responseDictionary objectForKey:@"success"]) {
NSLog(@"Session ended");
}
else {
NSLog(@"Error ending session");
}
}];
// Handle request failure
[request setFailedBlock:^{
NSError *error = [request error];
NSLog(@"Service error: %@", error.localizedDescription);
}];
// Start the request synchronously since the background service
// is already running on a background thread
[request startSynchronous];
}
@end
may be helped