to run app continuously in the background
Asked Answered
D

3

6

I want to my app to keep running in the background with location services. For this I have used:

-(void)applicationDidEnterBackground:(UIApplication *)application {

    [locationManager stopUpdatingLocation];
    [locationManager startUpdatingLocation];

    //timer=[NSTimer scheduledTimerWithTimeInterval:300 target:self selector:@selector(UpdateLocation) userInfo:nil repeats:YES];

}

but when I use NSTimer it does not call UpdateLocation. I tried calling it using another method but then it also called only once.

I want to run the app continuously in the background, detecting locations after regular interval of time.

Doralynn answered 16/10, 2010 at 5:27 Comment(0)
H
6

I did this in an application I'm developing. The timers don't work when the app is in the background but the app is constantly receiving the location updates. I read somewhere in the documentation (i can't seem to find it now, i'll post an update when i do) that a method can be called only on an active run loop when the app is in the background. The app delegate has an active run loop even in the bg so you dont need to create your own to make this work. [Im not sure if this is the correct explanation but thats how I understood from what i read]

First of all, add the 'location' object for the key 'Background Modes' in your app's info.plist. Now, what you need to do is start the location updates anywhere in your app:

CLLocationManager locationManager = [[CLLocationManager alloc] init];

locationManager.delegate = self;//or whatever class you have for managing location

[locationManager startUpdatingLocation];

Next, write a method to handle the location updates, say -(void)didUpdateToLocation:(CLLocation*)location, in the app delegate. Then implement the method locationManager:didUpdateLocation:fromLocation of CLLocationManagerDelegate in the class in which you started the location manager (since we set the location manager delegate to 'self'). Inside this method you need to check if the time interval after which you have to handle the location updates has elapsed. You can do this by saving the current time every time. If that time has elapsed, call the method UpdateLocation from your app delegate:

NSDate *newLocationTimestamp = newLocation.timestamp;
NSDate *lastLocationUpdateTiemstamp;

int locationUpdateInterval = 300;//5 mins

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if (userDefaults) {

        lastLocationUpdateTiemstamp = [userDefaults objectForKey:kLastLocationUpdateTimestamp];

        if (!([newLocationTimestamp timeIntervalSinceDate:lastLocationUpdateTiemstamp] < locationUpdateInterval)) {
            //NSLog(@"New Location: %@", newLocation);
            [(AppDelegate*)[UIApplication sharedApplication].delegate didUpdateToLocation:newLocation];
            [userDefaults setObject:newLocationTimestamp forKey:kLastLocationUpdateTimestamp];
        }
    }
}

This will call your method every 5 mins even when your app is in background. Imp: This implementation drains the battery, if your location data's accuracy is not critical you should use [locationManager startMonitoringSignificantLocationChanges]

Before adding this to your app, please read the Location Awareness Programming Guide at http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/Introduction/Introduction.html

Heligoland answered 23/6, 2011 at 7:38 Comment(1)
If I am not mistaken, this will only call didUpdateToLocation every 5 minutes if didUpdateLocation is called at regular small intervals. If you select startMonitoringSignificantChanges and do not move much, then you will not get updates at a 5 mn interval. Correct?Regen
A
0

I know this is very late for an answer. But if you still haven't got the answer, here is what I did and my app continuously runs in the background.

- (void)applicationDidEnterBackground:(UIApplication *)application
{
     UIApplication *app = [UIApplication sharedApplication];
     UIBackgroundTaskIdentifier bgTask = 0;

     backgroundTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self  selector:@selector(backgroundTask) userInfo:nil repeats:YES];

     bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
    }];
}

Now do whatever you want in the backgroundTask method.

Aprilaprile answered 20/12, 2012 at 6:38 Comment(4)
Is that located in the AppDelegate, or can this be in any class?Razid
yes, this code is in AppDelegate. And i've not tried it myself, but it should work in any other class too...Aprilaprile
There must be something I don't understand, because if I put this code and leave the method backgroundTask empty, my app runs in the background. If I remove your code, it doesn't anymore.Razid
what do you mean by, your app doesn't run in background if you remove the code.?? Did you check by putting an log in backgroundTask method?Aprilaprile
N
0

You can use for running app in background for particular task.

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    UIApplication *app = [UIApplication sharedApplication];
    UIBackgroundTaskIdentifier bgTask = 0;

    backgroundTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(backgroundTask) userInfo:nil repeats:YES];

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
    }];
}
Ne answered 29/4, 2013 at 6:13 Comment(2)
This appears to be the exact same solution that @Vish_Obj-C posted previously. What am I missing?Twinkling
Code looks wrong. The block will capture the value of bgTask when it is created, which is 0, leading to an incorrect [app endBackgroundTask:0]. Instead, you probably want to have a bgTaskID ivar/property, so the assignment can propagate to the block.Wattle

© 2022 - 2024 — McMap. All rights reserved.