Web service call in background mode - iOS

2019-08-13 03:20发布

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.

1条回答
成全新的幸福
2楼-- · 2019-08-13 03:41

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

查看更多
登录 后发表回答