Zachowanie w przypadku interfejsu API znaczącej zmiany lokalizacji po zakończeniu / zawieszeniu?

108

To jest sekcja z dokumentacji CLLocationManager opisująca zachowanie aplikacji za pomocą startMonitoringSsequantLocationChanges :

Jeśli uruchomisz tę usługę, a aplikacja zostanie następnie zamknięta, system automatycznie uruchomi ponownie aplikację w tle, jeśli nadejdzie nowe zdarzenie. W takim przypadku słownik opcji przekazany do aplikacji: didFinishLaunchingWithOptions: metoda delegata aplikacji zawiera klucz UIApplicationLaunchOptionsLocationKey wskazujący, że aplikacja została uruchomiona z powodu zdarzenia lokalizacji. Po ponownym uruchomieniu należy nadal skonfigurować obiekt menedżera lokalizacji i wywołać tę metodę, aby kontynuować odbieranie zdarzeń dotyczących lokalizacji. Po ponownym uruchomieniu usług lokalizacyjnych bieżące zdarzenie jest natychmiast dostarczane do pełnomocnika. Ponadto właściwość lokalizacji obiektu menedżera lokalizacji jest wypełniana najnowszym obiektem lokalizacji, jeszcze przed uruchomieniem usług lokalizacyjnych.

Rozumiem więc, że jeśli Twoja aplikacja zakończy działanie (i zakładam, że jeśli nie wywołasz stopMonitoringSsequantLocationChanges z applicationWillTerminate ), zostaniesz obudzony parametrem UIApplicationLaunchOptionsLocationKey do application: didFinishLaunchingWithOptions . W tym momencie tworzysz swój CLLocationManager , wywołujesz startMonitoringSsequantLocationChanges i przez ograniczony czas wykonujesz przetwarzanie lokalizacji w tle . Więc jestem w porządku z tym kawałkiem.

Poprzedni akapit mówi tylko o tym, co się dzieje, gdy aplikacja zostanie zamknięta, nie sugeruje, co zrobić, gdy aplikacja jest zawieszona. Dokumentacja didFinishLaunchingWithOptions mówi:

Aplikacja śledzi aktualizacje lokalizacji w tle, została wyczyszczona, a teraz została ponownie uruchomiona. W tym przypadku słownik zawiera klucz wskazujący, że aplikacja została ponownie uruchomiona z powodu nowego zdarzenia lokalizacji.

Sugeruje, że połączenie to zostanie odebrane dopiero po uruchomieniu aplikacji (z powodu zmiany lokalizacji) po rozwiązaniu.

Jednak akapit dotyczący usługi znaczących zmian w Przewodniku programowania rozpoznawania lokalizacji zawiera następujące informacje:

Jeśli pozostawisz tę usługę uruchomioną, a aplikacja zostanie następnie zawieszona lub zakończona, usługa automatycznie obudzi aplikację po nadejściu nowych danych o lokalizacji. W momencie budzenia aplikacja jest umieszczana w tle i ma niewielką ilość czasu na przetworzenie danych o lokalizacji. Ponieważ aplikacja działa w tle, powinna wykonywać minimalną pracę i unikać wszelkich zadań (takich jak wysyłanie zapytań do sieci), które mogłyby uniemożliwić jej powrót przed upływem przydzielonego czasu. Jeśli tak się nie stanie, Twoja aplikacja może zostać zamknięta.

Sugeruje to, że budzisz się z danymi o lokalizacji, jeśli Twoja aplikacja została zawieszona, ale nie wspomina o tym, jak się budzisz:

W trakcie pisania tego, myślę, że mogłem właśnie odpowiedzieć na moje własne pytanie, ale byłoby wspaniale, gdyby moje zrozumienie tego zostało potwierdzone przez kogoś bardziej kompetentnego.

RedBlueThing
źródło

Odpowiedzi:

80

Odkąd zadałem to pytanie, przeprowadziłem sporo testów (głównie w pociągu między domem a pracą) i potwierdziłem, że zachowanie zawieszonych aplikacji jest takie, jak podejrzewałem na końcu pytania.

Oznacza to, że Twoja zawieszona aplikacja jest budzona, nie otrzymujesz żadnych wywołań zwrotnych na temat delegata aplikacji, zamiast tego otrzymujesz aktualizacje lokalizacji za pośrednictwem istniejącego CLLocationManagerDelegate . Możesz wykryć, że pracujesz w tle, sprawdzając applicationState i wykonać ograniczoną pracę w przypadku wybudzenia ze stanu zawieszenia, aby wykonać przetwarzanie lokalizacji.

[UIApplication sharedApplication].applicationState == UIApplicationStateBackground

Doszedłem do tego wniosku dzięki uprzęży do testowania lokalizacji, którą możesz pobrać i wypróbować. Jest to dość prosta aplikacja, która umożliwia włączanie istotnych zmian i interfejsów API zmiany GPS za pośrednictwem interfejsu użytkownika i rejestrowanie wszystkich otrzymanych odpowiedzi.

Uwaga: Punkt szósty poprzedniej odpowiedzi jest nieprawidłowy. Liofilizowane zawieszone aplikacje otrzymują CLLocationManagerDelegate zwrotnych, gdy są one budzony ze stanu zawieszenia.

RedBlueThing
źródło
1
W mojej odpowiedzi wykreśliłem # 6, aby nie mylić ludzi.
Aaron,
Jak na ironię, czułem to samo zdezorientowanie, kiedy przygotowywałem się do znaczącej zmiany. Nadal mam wątpliwości, co się stanie, jeśli aplikacja zostanie zamknięta. czy wywołanie zwrotne UIApplicationDelegate nie nastąpi? czy to właściwy sposób uruchamiania aplikacji. jeśli menedżer lokalizacji nie został jeszcze uruchomiony, w jaki sposób może otrzymywać powiadomienia w tle? (czas na dalsze
prace
Wielkie dzięki za przykładową aplikację, była dla mnie bardzo przydatna. Mam pytanie: co jeśli korzystałem ze standardowej usługi lokalizacyjnej w tle, a nie tej znaczącej, czy w takim przypadku aplikacja zostanie ponownie uruchomiona po zakończeniu pracy? Zadałem tutaj szczegółowo to pytanie, byłbym zadowolony, gdybyś mógł mnie rozjaśnić:] stackoverflow.com/questions/12239967/…
aslisabanci
2
Nie działało na stackoverflow
Igor
Czy wiesz, ile czasu zajęło zamknięcie Twojej aplikacji? A potem zamiast tego uzyskać wywołanie zwrotne appDelegate? (Czy to jakieś 30 minut? 2 godziny? 5 godzin?) Pytam o to, ponieważ skonfigurowałem region do monitorowania. Wiele razy próbowałem zobaczyć, jak uruchamia się moja aplikacja, ale tylko wtedy, gdy ją ponownie uruchomiłem. Innym razem didExitRegionoddzwanianie, ale nie mogłem startLocationUpdatesstamtąd, ponieważ nie było to przez uruchomienie aplikacji ...
Kochanie
25

Moje rozumienie jest następujące (jestem w trakcie pisania aplikacji, która opiera się na tym API, ale nie ukończyłem tego komponentu na tyle, aby rozpocząć testowanie):

  1. Twoja aplikacja jest uruchamiana po raz pierwszy, rejestrujesz się w celu uruchomieniaMonitoringSsequantLocationChanges i udostępniasz funkcję wywołania zwrotnego. Gdy aplikacja jest uruchomiona, wywołuje to wywołanie zwrotne za każdym razem, gdy otrzyma znaczącą zmianę.
  2. Jeśli Twoja aplikacja zostanie umieszczona w tle, UIApplication otrzyma applicationWillResignActive , a następnie applicationDidEnterBackground .
  3. Jeśli Twoja aplikacja zostanie zabita, gdy jest zawieszona w tle, nie zostaniesz o tym powiadomiony; jeśli jednak Twoja aplikacja zostanie zabita podczas działania (o ile wiem, na pierwszym planie lub w tle), otrzymasz chwilę z applicationWillTerminate . Nie możesz zażądać dodatkowego czasu w tle z tej funkcji.
  4. Pomimo tego, że zostanie zabity w tle, system operacyjny ponownie uruchomi Twoją aplikację. Jeśli Twoja aplikacja jest po prostu uruchamiana przez system operacyjny dla zmiany, otrzymasz wezwanie do application didFinishLaunchingWithOptions :

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])

    pomoże Ci określić, czy wróciłeś ze zmiany lokalizacji w tle.

  5. Jeśli zamiast tego działałeś w tle, a Twoja aplikacja została ręcznie ponownie uruchomiona przez użytkownika, otrzymasz applicationWillEnterForeground, a po niej applicationDidBecomeActive .
  6. Niezależnie od tego, jak to się stało, po ponownym uruchomieniu aplikacji (chyba że nadal działała w tle w wyniku zadania w tle, a wspomniane zadanie zaczęło monitorować zmiany), musisz wyraźnie powiedzieć jej, aby ponownie uruchomiłaMonitoringSsequantLocationChanges, ponieważ wywołanie zwrotne nie jest dłużej przyczepiony po „liofilizacji”. I tak, wystarczy zaimplementować kod w didUpdateToLocation po ponownym podłączeniu pewnego rodzaju programu obsługi lokalizacji po powrocie ze stanu zawieszenia.

Właśnie tym zajmuję się teraz przy tworzeniu mojego kodu. Jak wspomniałem wcześniej, nie jestem jeszcze gotowy, aby przetestować to na urządzeniu, więc nie mogę stwierdzić, czy wszystko poprawnie zinterpretowałem, więc komentatorzy, zachęcam do poprawiania mnie (chociaż zrobiłem znaczną lekturę na temat).

Aha, a jeśli jakimś pechem wypuścisz aplikację, która robi to, co chcę, mógłbym płakać :)

Powodzenia!

Aaron
źródło
1
@Tegeril +1 Dzięki za odpowiedź. Zacząłem słyszeć na tym świerszcze. :) Dziwię się, że aplikacje, które zaczęły być zawieszone, muszą ponownie wywołać startMonitoringSsequantLocationChanges. Czy masz link do dokumentu, w którym jest to opisane? Zrozumiałem, że ładowanie ze stanu zawieszenia spowoduje utworzenie instancji wszystkich obiektów w taki sam sposób, jak w momencie zawieszenia aplikacji. Tak więc spodziewałbym się, że żądanie znaczącej zmiany wejdzie w życie.
RedBlueThing
Możesz o tym mówić? „Po ponownym uruchomieniu nadal musisz skonfigurować obiekt menedżera lokalizacji i wywołać tę metodę, aby kontynuować odbieranie zdarzeń dotyczących lokalizacji”. Myślę jednak, że odnosi się to do przypadku, gdy aplikacja została uruchomiona ze stanu zakończonego (przez zdarzenie lokalizacji). To jest w zasadzie źródło mojego pytania: „co się stanie z zawieszoną sprawą?”.
RedBlueThing
Morgan Grainger na forach Dev zasugerował: „Musisz utworzyć CLLocationManager, ustawić delegata i wywołać startMonitoringSsequantLocationChanges, gdy aplikacja zostanie uruchomiona, w przeciwnym razie Core Location nie będzie miał gdzie dostarczyć aktualizacji”. w kontekście ponownego uruchamiania aplikacji niezależnie od stanu zakończenia lub zawieszenia. Od „aplikacja została ponownie uruchomiona po rozpoczęciuMonitoringSsequantLocationChanges i co teraz?”
Aaron
Zgadzam się, że może to być nadal niejasne, nawet w kontekście tego postu na forum (plakat omawiał budzenie z tła, ale Morgan użył bardziej ogólnego ponownego uruchomienia aplikacji). Nadal uważam, że po ponownym uruchomieniu aplikacji musisz ponownie zadzwonić do monitora, jeśli chcesz pracować z funkcją znaczących zmian. Jeśli zamiast tego chcesz uruchomić zadanie w tle i zaktualizować za pomocą standardowej usługi lokalizacyjnej i funkcji GPS, jest to opcja alternatywna. Uważam jednak, że nie musisz ponownie rejestrować się przy każdym uruchomieniu ze znaczącymi zmianami, aby móc ponownie uruchomić.
Aaron
1
Cieszę się, że wyszło z tego coś definitywnego, powinno mi pomóc w przyszłości :)
Aaron
1

Jeśli aplikacja zostanie wywołana ze stanu zawieszenia w wyniku zmiany lokalizacji, aplikacja uruchomi się w tle.

Wszystkie obiekty będą aktywne i otrzymasz aktualizację lokalizacji w obecnym delegacie.

Anshu
źródło