2012-04-19 12 views
26

Próbuję wprowadzić sugestie podane w this post.Uzyskiwanie lokalizacji użytkownika co n minut po pobraniu aplikacji na tło

Niestety, kroki nie są dla mnie jasne. Próbowałem implementować te sugestie, ale funkcja backgroundTimeRemaining nadal się zmniejsza, nawet po uruchomieniu i zatrzymaniu usługi locationServices. W ten sposób rozwinąłem go:

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

    UIApplication* app = [UIApplication sharedApplication]; 

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

    // Start the long-running task and return immediately. 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Do the work associated with the task. 
     self.timer = nil; 
     [self initTimer]; 

    }); 
} 

initTimer:

- (void)initTimer { 

    // Create the location manager if this object does not 
    // already have one. 
    if (nil == self.locationManager) 
     self.locationManager = [[CLLocationManager alloc] init]; 

    self.locationManager.delegate = self; 
    [self.locationManager startMonitoringSignificantLocationChanges]; 

    if (self.timer == nil) { 
     self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3 
               target:self 
              selector:@selector(checkUpdates:) 
              userInfo:nil 
              repeats:YES]; 
    } 
} 

checkUpdates:

- (void)checkUpdates:(NSTimer *)timer{ 
    UIApplication* app = [UIApplication sharedApplication]; 
    double remaining = app.backgroundTimeRemaining; 
    if(remaining < 580.0) { 
     [self.locationManager startUpdatingLocation]; 
     [self.locationManager stopUpdatingLocation]; 
     [self.locationManager startMonitoringSignificantLocationChanges]; 
    } 
    DbgLog(@"Reminaing %f", app.backgroundTimeRemaining); 
} 

Czy ktoś ma sugestie na temat tego, co może być nie tak w moim kodu? Zarówno initTimer, jak i checkUpdates są wywoływane, ale tylko w czasie wykonywania w tle (+ - 10 min). Chcę, aby aplikacja aktualizowała lokalizację co n minut "na zawsze".

Moja aplikacja UIBackgroundModes jest ustawiona na lokalizację.

UPDATE:

Jestem teraz zresetowaniu timera didUpdateToLocation i didFailWithError. Ale wciąż backgroundTimeRemaining ciągle maleje:

- (void)locationManager:(CLLocationManager *)manager 
didUpdateToLocation:(CLLocation *)newLocation 
     fromLocation:(CLLocation *)oldLocation { 

NSLog(@"Did Update Location = %f/%f", [newLocation coordinate].latitude, [newLocation coordinate].longitude); 

UIApplication* app = [UIApplication sharedApplication]; 

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

// Start the long-running task and return immediately. 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    // Do the work associated with the task. 

    [self initTimer]; 

}); 
} 

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { 

[self.locationManager stopUpdatingLocation]; 
UIApplication* app = [UIApplication sharedApplication]; 

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

// Start the long-running task and return immediately. 
[self initTimer]; 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    // Do the work associated with the task. 

}); 

} 

Ja również unieważnienia timer:

- (void)checkUpdates:(NSTimer *)timer{ 
UIApplication* app = [UIApplication sharedApplication]; 
double remaining = app.backgroundTimeRemaining; 
if(remaining < 580.0 && remaining > 570.0) { 
    [self.timer invalidate]; 
    self.timer = nil; 
    [self.locationManager startUpdatingLocation]; 
    [self.locationManager stopUpdatingLocation]; 
} 
DbgLog(@"*************************Checking for updates!!!!!!!!!!! Reminaing %f", app.backgroundTimeRemaining); 
} 
+3

Czy Twoja aplikacja jest akceptowana w sklepie App Store? Zastanawiam się nad tym samym podejściem, ale muszę się upewnić, że moja aplikacja nie zostanie odrzucona. Dzięki Btw! – aslisabanci

+1

czy dostałeś to do pracy /? –

Odpowiedz

8

Po kilku dniach próbowania wszystkich możliwych rozwiązań udało mi się w końcu sprawić, by działało. Oto, co się dzieje w moim roztwór:

  • muszę konfiguracji UIBackgroundTaskIdentifiers, jeden dla timera, a inny dla locationManager

na moim rozwiązanie, wystarczy dodać:

UIApplication *app = [UIApplication sharedApplication]; 

bgTask2 = [app beginBackgroundTaskWithExpirationHandler:^{ 
[app endBackgroundTask:bgTask2]; 
bgTask2 = UIBackgroundTaskInvalid; }]; 

self.locationManager.delegate = self; 
[self.locationManager startUpdatingLocation]; 
+27

Do jakiej metody dodajesz te linie? – Michal

+0

@scurioni Czy możesz opublikować swój pełny działający kod? – Sharme

+0

Czy możesz podzielić się z nami roboczym kodem delegata aplikacji? doświadczamy tego samego problemu. –

4

Gdy jesteś w tle można mieć tylko 10 minut dodatkowego czasu. Nie ma sposobu na przedłużenie tego. Zamiast tego należy skorzystać z usług tła lokalizacji.

+1

i te usługi nie mają jeszcze wersji opartej na czasie, ale raczej są wyzwalane przy każdej aktualizacji lub znaczącej zmianie lokalizacji –

+0

Ale czytając post, który łączyłem, wydaje się, że ludzie byli w stanie to zrobić. Jak sądzisz, jaka jest różnica między tym, co zaimplementowałem, a kodem, który zrobili? – scurioni

+1

Podejście, którego używają (na pierwszy rzut oka), polega na korzystaniu z usługi lokalizowania w tle w pełnej mocy (dzięki czemu stale otrzymujesz aktualizacje, ale obsługujesz je tylko co X minut). To zadziała, ale twoja bateria umrze każdej nocy. –

9

Dla każdego, kto ma koszmar czasu próbującego to wymyślić, mam proste rozwiązanie.

  1. Przestudiuj przykład z raywenderlich.com. Przykładowy kod działa idealnie, ale niestety nie ma zegara podczas lokalizacji w tle. To będzie działać bezterminowo.
  2. Dodaj timera za pomocą tego fragmentu kodu:

    -(void)applicationDidEnterBackground { 
        [self.locationManager stopUpdatingLocation]; 
    
        UIApplication* app = [UIApplication sharedApplication]; 
    
        bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
        [app endBackgroundTask:bgTask]; 
        bgTask = UIBackgroundTaskInvalid; 
        }]; 
    
        self.timer = [NSTimer scheduledTimerWithTimeInterval:intervalBackgroundUpdate 
                   target:self.locationManager 
                   selector:@selector(startUpdatingLocation) 
                   userInfo:nil 
                   repeats:YES]; 
    } 
    
  3. Tylko nie zapomnij dodać „App rejestruje aktualizacje lokalizacji” w Info.plist.

+3

Skąd pochodzi 'bgTask'? – KKendall

+2

Właściwość (nieatomowa) UIBackgroundTaskIdentifier bgTask; w nagłówku klasa – HelmiB

+2

@HelmiB: Nie działa w systemie ** iOS 7 **, czy możesz zasugerować coś innego, muszę uruchomić lokalizatora w tle. – Optimistic

0

Kodeks Pracy (cały kod Stopniowe) Zmodyfikowany kod scurioni za

Krok 1

  • Idź na projekt -> Możliwości -> Tryby Tło -> Wybierz lokalizację aktualizacje.
  • Przejdź do projektu -> Informacje -> dodaj klucz NSLocationAlwaysUsageDescription z opcjonalnym ciągiem znaków.

Etap 2

Dodaj ten kod AppDelegate.m

@interface AppDelegate()<CLLocationManagerDelegate> 
@property (strong, nonatomic) CLLocationManager *locationManager; 
@property (strong, nonatomic) NSTimer *timer; 
@end 

Etap 3 Kod ten do applicationDidEnterBackground sposób w AppDelegate.m

- (void)applicationDidEnterBackground:(UIApplication *)application { 
     UIApplication *app = [UIApplication sharedApplication]; 
     __block UIBackgroundTaskIdentifier bgTaskId = 
     [app beginBackgroundTaskWithExpirationHandler:^{ 
      [app endBackgroundTask:bgTaskId]; 
      bgTaskId = UIBackgroundTaskInvalid; 
     }]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      self.timer = nil; 
      [self initTimer]; 
      [app endBackgroundTask:bgTaskId]; 
      bgTaskId = UIBackgroundTaskInvalid; 
     }); 
    } 

- (void)initTimer { 
    if (nil == self.locationManager) 
     self.locationManager = [[CLLocationManager alloc] init]; 

    self.locationManager.delegate = self; 
    [self.locationManager requestAlwaysAuthorization]; 
    [self.locationManager startMonitoringSignificantLocationChanges]; 
    if (self.timer == nil) { 
     self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3 
                 target:self 
                selector:@selector(checkUpdates:) 
                userInfo:nil 
                repeats:YES]; 
    } 
} 

- (void)checkUpdates:(NSTimer *)timer{ 
    UIApplication *app = [UIApplication sharedApplication]; 
    double remaining = app.backgroundTimeRemaining; 
    if(remaining < 580.0) { 
     [self.locationManager startUpdatingLocation]; 
     [self.locationManager stopUpdatingLocation]; 
     [self.locationManager startMonitoringSignificantLocationChanges]; 
    } 
} 

- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
      fromLocation:(CLLocation *)oldLocation { 
    NSLog(@"Did Update Location = %f/%f", [newLocation coordinate].latitude, [newLocation coordinate].longitude); 
    [self updateLocationWithLatitude:[newLocation coordinate].latitude andLongitude:[newLocation coordinate].longitude]; 
    UIApplication* app = [UIApplication sharedApplication]; 
    __block UIBackgroundTaskIdentifier bgTask = 
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
     [app endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [self initTimer]; 
    }); 
} 

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { 
    [self.locationManager stopUpdatingLocation]; 
    UIApplication *app = [UIApplication sharedApplication]; 
    __block UIBackgroundTaskIdentifier bgTask = 
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
     [app endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 
    [self initTimer]; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     // Do the work associated with the task 
    }); 
} 

-(void)updateLocationWithLatitude:(CLLocationDegrees)latitude 
        andLongitude:(CLLocationDegrees)longitude{ 
//Here you can update your web service or back end with new latitude and longitude 
} 
Powiązane problemy