2013-11-25 9 views
7

testowania urządzenia: iPhone 5 (iOS 7)StartUpdateLocations w tle, didUpdatingToLocation wywołana tylko 10-20 razy

mam aplikację, która wykorzystuje RegionMonitoring i updateLocation. Jeśli wprowadzono region, didEnterRegion jest wywoływane zgodnie z oczekiwaniami. Następnie dzwonię pod numer startUpdatingLocation. Ale metoda didUpdateToLocation jest wywoływana tylko 10-20 razy, podczas gdy powinna aktualizować lokalizację do czasu uruchomienia timera.

Odpowiedni kod:

CLLocationManager *_locationManager; 
NSTimer *_timer; 

-(void)initLocationManager 
{ 
    _locationManager = [[CLLocationManager alloc] init]; 
    _locationManager.delegate = self; 
    [_locationManager setActivityType:CLActivityTypeOther]; 
    [_locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation]; 
    [_locationManager setPausesLocationUpdatesAutomatically:NO]; 
    [_locationManager setDistanceFilter:kCLDistanceFilterNone]; 
} 


//Did Enter Region, called as expected: 
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region 
{ 
    [_locationManager startUpdatingLocation]; 
    _timer = [NSTimer scheduledTimerWithTimeInterval:300.0f target:self selector:@selector(scheduleMethod:) userInfo:nil repeats:NO]; 
} 


//Timer Fire Method: 
- (void) scheduleMethod:(NSTimer*)timer 
{ 
    [Utils writeToLog:@"Timer-Stop"]; 
    [_locationManager stopUpdatingLocation]; 
} 


//This Method only called 10-20 Times (in the first 10-20 Seconds) and not the complete 5 Minutes: 
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    [Utils writeToLog:@"LocationUpdate!"]; 
} 

Do tej pory próbowałem: Ponowne uruchomienie aktualizacji w metodzie locationManagerDidPauseLocationUpdates, ale wydaje się, że to nigdy się nazywać:

-(void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager 
{ 
    [WRUtils writeToLog:@"LocationUpdate paused, restarted"]; 
    [_locationManager startUpdatingLocation]; 
} 

sprawdzić błędy w metoda didFailWithError, ale to też się nie nazywa. i grał trochę z właściwościami:

[_locationManager setActivityType:CLActivityTypeOther]; 
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation]; 
[_locationManager setPausesLocationUpdatesAutomatically:NO]; 

ustawienia PLIST rację Chyba: Wymagane tryby tło TAK Wymagane Tryby tła pozycja 0 App rejestruje aktualizacje lokalizacji

Jak mogę rozwiązać ten problem?

Odpowiedz

23

Apple wprowadził nową politykę w iOS 7. iOS 7 nie dostarcza już aktualizacji lokalizacji w tle, jeśli wywołasz "startUpdatingLocation", gdy aplikacja jest w tle. Dostajesz aktualizację tylko wtedy, gdy aplikacja zostanie przeniesiona na pierwszy plan w tym przypadku.

Gdy korzystasz z funkcji geofencing, Twoja aplikacja otrzymuje kilka sekund za każdym razem, gdy otrzymasz powiadomienie o regionie/Exited, aby przetworzyć to powiadomienie. W tych kilku sekundach możesz również uzyskać aktualizacje lokalizacji. Po tych kilku sekundach po iOS 7 po prostu zawiesza twoją aplikację ponownie.

Możesz użyć zadania w tle, aby uzyskać więcej niż kilka sekund, ale w systemie iOS 7 Apple skróciło także czas uruchamiania aplikacji w tle z 10 minut (iOS 6 i starszych) do zaledwie 3 minut w systemie iOS 7 .Wygląda na to, że te 3 minuty to łączna kwota za cały czas, gdy aplikacja jest w tle. Oznacza to, że nie możesz poprosić iOS 7 10 razy, aby uzyskać 1 minutę czasu tła, dostaniesz tylko 3 minuty w sumie, więc po 3 razie poprosisz o minutę, Twoja aplikacja nie będzie już więcej czasu w tle w ogóle.

Twoja jedyna szansa na uzyskanie aktualizacji lokalizacji w tle to wywołanie "startUpdatingLocation", gdy aplikacja znajduje się na pierwszym planie. Jest to szczególnie smutne, gdy potrzebujesz aktualizacji lokalizacji tylko w odpowiedzi na wiadomości Regionu (Enter/Exit), ponieważ musisz ciągle aktualizować lokalizacje, ale możesz przynajmniej zmniejszyć zużycie baterii, ustawiając wartość dokładności na kCLLocationAccuracyThreeKilometers when nie trzeba aktualizacji lokalizacji i ustawić dokładność kCLLocationAccuracyBest tylko wtedy, gdy naprawdę musisz współrzędne geograficzne. iOS nie będzie zasilić GPS wartości kCLLocationAccuracyThreeKilometers, więc korzystanie z baterii będzie umiarkowane w tym przypadku.

Również wartość kCLLocationAccuracyBestForNavigation dla dokładności wydaje się powodować problemy w systemie IOS 7. Nie otrzymuję aktualizacji lokalizacji o tej wartości, jeśli urządzenie nie jest podłączone do zewnętrznego źródła zasilania.

W sumie nowa polityka iOS 7 dotycząca aktualizacji lokalizacji znacznie utrudnia rozwój niektórych rodzajów aplikacji. Zamiast rejestrować aktualizacje lokalizacji tylko w razie potrzeby, jesteś zmuszony do zarejestrowania się w nich na czas trwania swojej aplikacji. Co oczywiście powoduje szybsze rozładowanie baterii, chociaż intencja Apple'a dla tej nowej polityki była prawdopodobnie odwrotna.

UPDATE:

Po pewnym więcej testów Znalazłem jakieś rozwiązanie dla tego problemu. Dokumenty od Apple wspominają, że podczas korzystania z interfejsu API znaczącej zmiany lokalizacji aplikacje mogą odbierać aktualizacje lokalizacji w tle, nawet jeśli "startUpdatingLocation" jest uruchamiana w tle.

Moje pierwsze testy nie działały dobrze. Rejestruję aplikację w poszukiwaniu znaczących aktualizacji lokalizacji w ramach metod delegowania monitorowania regionu tuż przed wywołaniem funkcji startUpdatingLocation (dlatego ta usługa lokalizacji jest włączona tylko w razie potrzeby), ale nadal nie dostarcza aktualizacji lokalizacji w tle, co sugerują dokumenty.

Ale jeśli zaczniesz słuchać znaczących zmian lokalizacji bezpośrednio po uruchomieniu aplikacji (i nigdy jej nie wyłączasz), możesz zadzwonić pod numer "startUpdatingLocation", gdy aplikacja jest w tle, a także otrzymywać aktualizacje lokalizacji w tle. Zużycie baterii przez cały czas posiadające funkcję "znaczącej zmiany lokalizacji" wydaje się być bardzo niskie, więc prawdopodobnie będzie to rozwiązanie dla większości aplikacji:

Musisz sprawdzić, czy funkcja "znaczącej zmiany lokalizacji" jest dostępne na urządzeniu, ale wydaje się, że obsługują to wszystkie obecne urządzenia. Nawet 5. generacji iPoda Touch obsługuje je (iPod Touch nie może używać wież komórkowych do aktualizacji lokalizacji, która jest podstawową metodą tej funkcji, zgodnie z dokumenty od Apple, więc przypuszczam, że możemy założyć, że wszystkie obecne urządzenia z systemem iOS 7 mogą korzystać z interfejsu API "znaczna aktualizacja lokalizacji". Chociaż prawdopodobnie warto sprawdzić, czy ta funkcja jest rzeczywiście dostępna, być może istnieją pewne okoliczności, w których funkcja jest niedostępne)

Korzystanie z funkcji API "istotna zmiana lokalizacji" może mieć jedną wadę: aplikacja może być uruchomiona w tle (jeśli została zakończona w tle przez system iOS w celu ponownego użycia jej pamięci dla innych aplikacji) wielokrotnie i niepotrzebnie po każdym przeniesieniu urządzenia " znacznie "(zgodnie z dokumentami: kiedy wieża celna się zmieniła, ale nie więcej niż raz na 5 minut). Tak więc aplikacje, które trzeba tylko aktywować, kiedy dany region zostanie opuszczony lub wprowadzony, będą uruchamiane, a informacje o lokalizacji będą się zmieniać cały czas, nie tylko w tych regionach.Zakładam jednak, że to powinno być znacznie lepsze niż ciągłe uaktualnianie standardowych aktualizacji.

Mój iPhone 5s wyczerpuje baterię tylko o 1% w ciągu nocy przy znaczących zmianach lokalizacji aktywnych, zamiast o 12% przy włączonych standardowych aktualizacjach lokalizacji z dokładnością do 3 km.

Mam nadzieję, że pomoże to wszystkim programistom, którzy zmagają się z nowym zachowaniem na iOS 7.

+0

Twoja sztuczka polegająca na "uruchomieniu na pierwszym planie i ustawieniu na tryb pracy" działa, ale zamiast 10% energii zużywa 50% baterii w ciągu 24 godzin. To znacznie więcej! Cholera, dlaczego nie mogę po prostu rozpocząć aktualizowania lokalizacji w tle dla konkretnego regionu ... :(Jeśli masz inne pomysły, daj mi znać: – flo

+0

Przynajmniej na moim iPhone 5s zużycie baterii wydaje się być na tyle umiarkowane, aby być Wydaje mi się, że iOS używa nowego układu M7 do sprawdzania, czy urządzenie się porusza, a jeśli leży na stole przez całą noc, iOS wie, że lokalizacja nie mogła się zmienić, a zatem nawet nie próbuje uzyskać lokalizacji Aktualizacje w celu oszczędzania energii Na urządzeniach, które nie mają chipa M7, sytuacja jest inna - Proponuję wysłać zgłoszenie błędu/funkcję do Apple, może jeśli wystarczająco dużo programistów to robi, rozważają powrót do stare zachowanie ... – Alex

+0

Hi im przy użyciu geofencing z startMonitoringSignificantLocationChanges.Gdy znacząca zmiana lokalizacji w trybie tła, to uzyskać aktualny serwer połączenia lokalizacji i uzyskać nowe lokalizacje, i ustawić na geofencing.Myślę, że jest ok z nowej polityki Apple. @Glin powiedz mi, czy to jest ok. – mychar

0

w tle czasomierza nie będzie działać, więc tutaj Twój obiekt Timer nie będzie reagować, trzeba utworzyć obsługi zadania w tle, sprawdź komentarz poniżej linku

How to run the timer in background of the application?

W tle, jeśli chcesz, aby kontynuować usługa lokalizacji niż trzeba ustawić pausesLocationUpdatesAutomatically flagi, info flagi na

pausesLocationUpdatesAutomatically flag info

if ([self.locationManager respondsToSelector:@selector(pausesLocationUpdatesAutomatically)]) { 
    self.locationManager.pausesLocationUpdatesAutomatically = NO; 
    } 

sprawdź mój komentarz na Location service going to "Inactive" state in iPhone 5

Dla menedżera lokalizacji tam poniżej są metody CLLocationManagerDelegate o aktualizacji lokalizacji,

- (void)locationManager:(CLLocationManager *)manager 
didUpdateToLocation:(CLLocation *)newLocation 
     fromLocation:(CLLocation *)oldLocation [Deprecated in __IPHONE_6_0] 

    - (void)locationManager:(CLLocationManager *)manager 
didUpdateLocations:(NSArray *)locations __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0); 

Gdzie znalazłeś

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation ?? 
+0

Dzięki za podpowiedź z samowyzwalaczem, ale ustawić pauseLocationUpdateAutomatically NO (patrz wyżej mój przykładowy kod.) I metoda didUpdatingToLocation jest tylko 10-20 razy z tą inicjacją. – flo

+0

Dlaczego użyłeś _timer - (void) scheduleMethod: (NSTimer *) timer, aby zatrzymaćUpdatingLocation? –

+0

Ponieważ muszę wprowadzić statystykę ruchu na 5 minut, jeśli zostanie wprowadzona strefa geofence (odległość, prędkość, a po 5 minutach zatrzymam się w celu ustalenia lokalizacji), masz rację, że to działa w tle, więc muszę to zrobić za pomocą Ale moje pytanie jest, dlaczego przestaje wywoływać didupdateToLocation (timer nie działa, że ​​nauczyłem się teraz), więc stopUpdatetingLocation nigdy nie zadzwonił ... ale to po prostu przestaje aktualizować – flo

0

skorzystać z poniższego kodu w metodzie didEnterRegion do uruchomienia aktualizacji ponownie

[_locationManager startMonitoringSignificantLocationChanges]; 
if ([_locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) 
{ 
    _locationManager.allowsBackgroundLocationUpdates =YES; 

} 
[_locationManager startUpdatingLocation]; 
Powiązane problemy