2010-10-16 8 views
6

Quiero que mi aplicación se ejecute en segundo plano con los servicios de ubicación. Para esto he utilizado:para ejecutar la aplicación continuamente en el fondo

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

    [locationManager stopUpdatingLocation]; 
    [locationManager startUpdatingLocation]; 

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

} 

pero cuando se utiliza NSTimer no llama UpdateLocation. Intenté llamarlo usando otro método, pero luego también lo llamé solo una vez.

Quiero ejecutar la aplicación continuamente en segundo plano, detectando ubicaciones después de un intervalo de tiempo regular.

Respuesta

5

Lo hice en una aplicación que estoy desarrollando. Los temporizadores no funcionan cuando la aplicación está en segundo plano, pero la aplicación recibe constantemente las actualizaciones de ubicación. Leí en algún lugar de la documentación (parece que no puedo encontrarlo ahora, publicaré una actualización cuando lo hago) que un método puede invocarse solo en un ciclo de ejecución activo cuando la aplicación está en segundo plano. El delegado de la aplicación tiene un bucle de ejecución activo incluso en el bg, por lo que no es necesario que crees el tuyo para que esto funcione. [No estoy seguro si esta es la explicación correcta, pero así es como entiendo por lo que leo]

Antes que nada, agregue el objeto 'ubicación' para la clave 'Modos de fondo' en la aplicación de info.plist. Ahora, lo que hay que hacer es empezar las actualizaciones de ubicación en cualquier lugar de su aplicación:

CLLocationManager locationManager = [[CLLocationManager alloc] init]; 

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

[locationManager startUpdatingLocation]; 

A continuación, escribir un método para manejar las actualizaciones de ubicación, dicen - (void) didUpdateToLocation: (CLLocation *) ubicación, en el delegado de la aplicación. A continuación, implemente el método locationManager: didUpdateLocation: fromLocation de CLLocationManagerDelegate en la clase en la que inició el administrador de ubicaciones (ya que configuramos el delegado del administrador de ubicaciones en 'self'). Dentro de este método, debe verificar si ha transcurrido el intervalo de tiempo después del cual debe manejar las actualizaciones de ubicación. Puede hacer esto guardando la hora actual cada vez. Si ha transcurrido ese tiempo, llame al método UpdateLocation del delegado de la aplicación:

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]; 
     } 
    } 
} 

Esto le llame a su método cada 5 minutos, incluso cuando su aplicación está en segundo plano. Imp: Esta aplicación drena la batería, si la precisión de sus datos de localización no es crítico que debe utilizar [locationManager startMonitoringSignificantLocationChanges]

Antes de añadir esto a su aplicación, por favor lea la Guía de programación de Conocimiento de ubicación en http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/Introduction/Introduction.html

+0

Si no me equivoco, esto sólo llamar didUpdateToLocation cada 5 minutos si didUpdateLocation se llama a intervalos regulares pequeños. Si selecciona startMonitoringSignificantChanges y no se mueve mucho, no obtendrá actualizaciones en un intervalo de 5 minutos. ¿Correcto? – Lolo

0

I sé que esto es muy tarde para una respuesta. Pero si aún no tiene la respuesta, esto es lo que hice y mi aplicación se ejecuta continuamente en segundo plano.

- (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]; 
    }]; 
} 

Ahora hacer lo que quiera en el método debackgroundTask.

+0

¿Está ubicado en AppDelegate o puede ser de cualquier clase? – anthoprotic

+0

sí, este código está en AppDelegate. Y yo no lo he probado, pero debería funcionar en cualquier otra clase también ... –

+0

Debe haber algo que no entiendo, porque si pongo este código y dejo el método backgroundTask vacío, mi aplicación se ejecuta en segundo plano. Si elimino tu código, ya no funciona. – anthoprotic

0

Puede utilizar para ejecutar la aplicación en segundo plano para una tarea en particular.

- (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]; 
    }]; 
} 
+0

Esta parece ser la misma solución que @ Vish_Obj-C publicada anteriormente. ¿Qué me estoy perdiendo? – smholloway

+0

El código parece incorrecto. El bloque capturará el valor de 'bgTask' cuando se crea, que es 0, lo que lleva a un' [app endBackgroundTask: 0] 'incorrecto. En cambio, es probable que desee tener una propiedad/bgTaskID, por lo que la asignación se puede propagar al bloque. –

Cuestiones relacionadas