2010-10-16 1 views
6

Voglio che la mia app continui a funzionare in background con i servizi di localizzazione. Per questo ho usato:per eseguire l'app in modo continuo in background

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

    [locationManager stopUpdatingLocation]; 
    [locationManager startUpdatingLocation]; 

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

} 

, ma quando uso NSTimer non chiama UpdateLocation. Ho provato a chiamarlo usando un altro metodo, ma poi ha anche chiamato solo una volta.

Voglio eseguire l'app in modo continuo in background, rilevando le posizioni dopo un intervallo di tempo regolare.

risposta

5

Ho fatto questo in un'applicazione sto sviluppando. I timer non funzionano quando l'app è in background ma l'app riceve costantemente gli aggiornamenti di posizione. Ho letto da qualche parte nella documentazione (non riesco a trovarlo ora, pubblicherò un aggiornamento quando lo faccio) che un metodo può essere chiamato solo su un ciclo di esecuzione attivo quando l'app è in background. Il delegato dell'app ha un ciclo di esecuzione attivo anche in bg, quindi non è necessario crearne uno per farlo funzionare. [Non sono sicuro se questa è la spiegazione corretta ma questo è il modo in cui ho capito da quello che ho letto]

Prima di tutto, aggiungi l'oggetto "posizione" per la chiave "Modalità di background" nel file info.plist dell'app. Ora, ciò che devi fare è iniziare gli aggiornamenti sulla posizione in qualsiasi punto della app:

CLLocationManager locationManager = [[CLLocationManager alloc] init]; 

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

[locationManager startUpdatingLocation]; 

Avanti, scrivere un metodo per gestire gli aggiornamenti sulla posizione, dicono - (void) didUpdateToLocation: (CLLocation *) posizione, in il delegato dell'app. Quindi implementare il metodo locationManager: didUpdateLocation: fromLocation di CLLocationManagerDelegate nella classe in cui è stato avviato il gestore località (poiché abbiamo impostato il delegato del gestore località su "self"). All'interno di questo metodo è necessario verificare se è trascorso l'intervallo di tempo dopo il quale è necessario gestire gli aggiornamenti di posizione. Puoi farlo salvando l'ora corrente ogni volta. Se questo tempo è trascorso, chiamare il metodo UpdateLocation dalla tua app delegato:

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

Questo chiamerà il metodo di ogni 5 minuti, anche quando la vostra applicazione è in background. Imp: Questa implementazione drena la batteria, se la precisione dei vostri dati di localizzazione non è critico si dovrebbe usare [locationManager startMonitoringSignificantLocationChanges]

Prima di aggiungere questo alla vostra applicazione, si prega di leggere la Guida alla programmazione di sensibilizzazione posizione a http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/Introduction/Introduction.html

+0

Se non erro, questo richiamerà didUpdateToLocation solo ogni 5 minuti se viene richiamata didUpdateLocation a intervalli regolari regolari. Se selezioni startMonitoringSignificantChanges e non ti sposti molto, non otterrai aggiornamenti a intervalli di 5 minuti. Corretta? – Lolo

0

I so che è molto tardi per una risposta. Ma se ancora non hai la risposta, ecco cosa ho fatto e la mia app viene eseguita continuamente in 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]; 
    }]; 
} 

Ora fare quello che vuoi nel metodo di BackgroundTask.

+0

È situato in AppDelegate o può essere in qualsiasi classe? – anthoprotic

+0

sì, questo codice si trova in AppDelegate. E non l'ho provato da solo, ma dovrebbe funzionare anche in qualsiasi altra classe ... –

+0

Deve esserci qualcosa che non capisco, perché se inserisco questo codice e lascia vuoto il metodo backgroundTask, la mia app viene eseguita in background. Se rimuovo il tuo codice, non lo fa più. – anthoprotic

0

È possibile utilizzare per l'esecuzione di applicazioni in background per particolari attività.

- (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

Questa sembra essere la stessa identica soluzione che @ Vish_Obj-C ha pubblicato in precedenza. Cosa mi manca? – smholloway

+0

Il codice sembra sbagliato. Il blocco acquisirà il valore di 'bgTask' quando viene creato, che è 0, portando a un' [app endBackgroundTask: 0] 'errato. Invece, probabilmente vorrai avere una bgTaskID ivar/property, quindi il compito può propagarsi al blocco. –