Czy iOS uruchomi moją aplikację w tle, jeśli użytkownik wymusił jej zamknięcie?

219

Uruchamiam pobieranie w tle za pomocą content-availableflagi w powiadomieniu wypychanym. Mam fetchi remote-notification UIBackgroundModeswłączone.

Oto implementacja, której używam w mojej AppDelegate.m:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    NSLog(@"Remote Notification Recieved");
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.alertBody =  @"Looks like i got a notification - fetch thingy";
    [application presentLocalNotificationNow:notification];
    completionHandler(UIBackgroundFetchResultNewData);

}

Gdy aplikacja działa w tle, działa dobrze. (Powiadomienie zostało odebrane, a aplikacja uruchomiła powiadomienie lokalne „wygląda na to, że dostałem powiadomienie”, tak jak powinien to zrobić powyższy kod).

Jednak gdy aplikacja nie działa, a content-availableflagę otrzymuje powiadomienie wypychane , aplikacja nie jest uruchamiana, a didRecieveRemoteNotificationmetoda delegowania nigdy nie jest wywoływana.

Wideo WWDC Co nowego w wielozadaniowości (nr 204 z WWDC 2013) pokazuje to:wprowadź opis zdjęcia tutaj

Mówi, że aplikacja jest „uruchamiana w tle” po otrzymaniu powiadomienia wypychanego z content-availableflagą.

Dlaczego moja aplikacja nie uruchamia się w tle?

Tak więc prawdziwe pytanie brzmi:

Czy iOS wykona zadania w tle po tym, jak użytkownik wymusi zamknięcie aplikacji?

Święty Mikołaj
źródło
Jak sprawdzasz, czy aplikacja uruchamia się w tle?
runmad
1
@runmad Loguję kilka gówna w- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Święty Mikołaj
Jak się logujesz, po prostu NSLog? Będziesz musiał ustawić Uruchom na ręczny w ustawieniach schematu aplikacji (patrz odpowiedź)
runmad 28.09.2013
@runmad patrz komentarz do odpowiedzi
Święty Mikołaj
@HaimBenchimol Djd otrzymujesz odpowiedź na zgłoszenie błędu? Nie udało mi się złożyć własnego zgłoszenia błędu.
Święty Mikołaj,

Odpowiedzi:

215

AKTUALIZACJA 2:

Możesz to osiągnąć za pomocą nowej struktury PushKit, wprowadzonej w iOS 8. Chociaż PushKit jest używany do VoIP. Dlatego należy korzystać z VoIP, w przeciwnym razie istnieje ryzyko odrzucenia aplikacji. (Zobacz tę odpowiedź ).


UDPDATE1:

Dokumentacja została wyjaśniona dla iOS8 . Dokumentację można przeczytać tutaj . Oto odpowiedni fragment:

Ta metoda służy do przetwarzania przychodzących zdalnych powiadomień dotyczących aplikacji. W przeciwieństwie do application:didReceiveRemoteNotification:metody, która jest wywoływana tylko wtedy, gdy aplikacja działa na pierwszym planie, system wywołuje tę metodę, gdy aplikacja działa na pierwszym planie lub w tle. Ponadto, jeśli włączyłeś tryb zdalnych powiadomień w tle, system uruchamia twoją aplikację (lub budzi ją ze stanu zawieszonego) i ustawia w tle, gdy nadejdzie powiadomienie push. Jednak system nie uruchamia automatycznie Twojej aplikacji, jeśli użytkownik ją wymusił. W takiej sytuacji użytkownik musi ponownie uruchomić aplikację lub ponownie uruchomić urządzenie, zanim system spróbuje ponownie uruchomić aplikację automatycznie.


Chociaż wideo WWDC tego nie wyjaśniło, pojawiło się szybkie wyszukiwanie na forach programistów:

https://devforums.apple.com/message/873265#873265 (wymagane logowanie)

Pamiętaj również, że jeśli zabijesz aplikację za pomocą przełącznika aplikacji (tzn. Przesuniesz w górę, aby zabić aplikację), system operacyjny nigdy nie uruchomi aplikacji ponownie, niezależnie od powiadomienia wypychania lub pobrania w tle. W takim przypadku użytkownik musi raz ręcznie ręcznie uruchomić aplikację, a następnie od tego momentu zostaną uruchomione działania w tle. - pmarcos

Ten post został napisany przez pracownika Apple, więc myślę, że mogę ufać, że te informacje są prawidłowe.

Wygląda więc na to, że gdy aplikacja zostanie zabita z przełącznika aplikacji (przez przesunięcie w górę), aplikacja nigdy nie zostanie uruchomiona, nawet w przypadku zaplanowanych pobrań w tle.

Święty Mikołaj
źródło
2
Dla mnie dodanie akcji w „didFinishLaunchingWithOptions”, gdy opcje uruchamiania nie są zerowe, zadziałało. Mam tutaj tę samą metodę, co w „didreceiveRemoteNotification”
harsh.prasad
@ harsh.prasad to ciekawe. Problem polegał na tym, że aplikacja nie została uruchomiona, gdy aplikacja została zabita z przełącznika aplikacji.
Święty Mikołaj
3
Aplikacja nie musi być wyświetlana w przełączniku aplikacji, jeśli odebrano cichy push. Można go uruchomić w tle bez dodawania go do przełącznika aplikacji, można go uruchomić i „zrobić to”, a następnie wyjść. Aplikacje, które pozostają zbyt długo aktywne, zostaną zabite w taki sam sposób, jak już są.
MindJuice
1
@chrizstone Rozwiązaniem jest to, że jest to zamierzone zachowanie i nie można nic z tym zrobić.
Święty Mikołaj
1
@JPK Uh, same powiadomienia push nie ulegają zmianie. Po prostu wykonuje zadania w tle, które nie będą działać po wymuszonym zakończeniu pracy.
Święty Mikołaj
70

Możesz zmienić ustawienia uruchamiania celu w „Zarządzaj schematem” na Wait for <app>.app to be launched manually, co pozwala na debugowanie poprzez ustawienie punktu przerwania application: didReceiveRemoteNotification: fetchCompletionHandler:i wysyłanie powiadomienia wypychania w celu uruchomienia uruchamiania w tle.

Nie jestem pewien, czy to rozwiąże problem, ale na razie może ci pomóc w debugowaniu.

zrzut ekranu

runmad
źródło
więc to pomogło, ale problem nadal występuje
Święty Mikołaj
Dziwne. Zakładam, że ponad dwukrotnie sprawdziłeś, czy wszystkie lampy błyskowe są ustawione na liście itp.?
runmad
Wiem też, że wszystko mam ustawione poprawnie, ponieważ gdy aplikacja jest w tle, wszystko działa idealnie. Jest tak, gdy aplikacja w ogóle nie działa, a nie działa.
Święty Mikołaj
Zastanawiam się, czy wyzwalacz powiadomień wypychanych jest determinowany przez system. Na przykład, jeśli iOS stwierdzi, że nie jest to najlepszy moment na uruchomienie aplikacji w tej chwili, może ją odłożyć na później. Być może spróbuj zamknąć wszystkie uruchomione aplikacje / działające w tle i zobaczyć, co się stanie? Zgaduję tylko w tym momencie: - /
runmad
właśnie tego spróbowałem. Nic się nie stało, tak jak zwykle. Mogę zapytać na forach deweloperów.
Święty Mikołaj
37

Odpowiedź brzmi TAK, ale nie należy używać opcji „Pobieranie w tle” lub „Zdalne powiadomienie”. PushKit to odpowiedź, której pragniesz.

Podsumowując, PushKit, nowa platforma w systemie iOS 8, to nowy mechanizm powiadomień wypychanych, który może cicho uruchamiać aplikację w tle bez wizualnego powiadomienia, nawet gdy aplikacja została zabita przez przesunięcie z przełącznika aplikacji, co zadziwiające, nawet jej nie widzisz z przełącznika aplikacji.

Referencje PushKit od Apple:

Struktura PushKit zapewnia klasy dla aplikacji iOS do odbierania wypychania ze zdalnych serwerów. Wypychania mogą być jednego z dwóch rodzajów: standardowego i VoIP. Standardowe wypychania mogą dostarczać powiadomienia tak jak w poprzednich wersjach iOS. Wypychania VoIP zapewniają dodatkową funkcjonalność oprócz standardowego wypychania potrzebnego aplikacjom VoIP do wykonywania przetwarzania wypychania na żądanie przed wyświetleniem powiadomienia użytkownikowi.

Aby wdrożyć tę nową funkcję, zapoznaj się z tym samouczkiem: https://zeropush.com/guide/guide-to-pushkit-and-voip - przetestowałem ją na moim urządzeniu i działa zgodnie z oczekiwaniami.

superZhen
źródło
9
Wygląda na to, że musisz ustawić swoją aplikację jako korzystającą z VoIP. Jeśli twoja aplikacja nie jest aplikacją VoIP, czy nie zostanie po prostu odrzucona podczas przeglądu?
duncanc4
6
Niestety, znając proces sprawdzania poprawności przez Apple, logiczne byłoby odrzucenie aplikacji.
Kepa Santos,
3
Używany do VoIP. Jeśli użytkownik nie korzysta z VoIP dla użytkownika, znacznie zwiększy to ryzyko odrzucenia recenzji.
Chris,
Wygląda na to, że duzi dostawcy używają tego narzędzia jako pretekstu, aby uruchamiać rzeczy w tle, a Apple przymyka oczy. Stanie się Androidem jedną funkcją na raz.
TCB13
PushKit jest zarezerwowany dla VoIP, dostawców plików i oglądania komplikacji. Nie jest dostępna dla przypadków użycia opisanych w tej odpowiedzi.
quellish
15

W rzeczywistości, jeśli chcesz przetestować pobieranie w tle, musisz włączyć jedną opcję w schemacie:

włączanie pobierania bg

Kolejny sposób, w jaki możesz to przetestować: symuluj pobieranie bg

Oto pełne informacje na temat tej nowej funkcji: http://www.objc.io/issue-5/multitasking.html

Danil
źródło
4

Próbowałem różnych wariantów tego od kilku dni i przez jeden dzień myślałem, że ponownie uruchamiam aplikację w tle, nawet gdy użytkownik przesunął palcem, aby zabić, ale nie, nie mogę odtworzyć tego zachowania.

Szkoda, że ​​zachowanie jest zupełnie inne niż wcześniej. Na iOS 6, jeśli zabijesz aplikację z poruszających się ikon, nadal będzie budzona ponownie po wyzwalaczach SLC. Teraz, jeśli zabijesz, przesuwając, tak się nie stanie.

To inne zachowanie, a użytkownik, który nadal uzyskiwałby użyteczne informacje z naszej aplikacji, gdyby zabił je na iOS 6, teraz tego nie zrobi.

Musimy szturchnąć naszych użytkowników, aby ponownie otworzyli aplikację teraz, jeśli przesunęli palcem, aby ją zabić i nadal oczekują niektórych zachowań powiadomień, które im daliśmy. Obawiam się, że nie będzie to oczywiste dla użytkowników, gdy przeciągną aplikację. Mogą to być w zasadzie czyszczenie lub chęć zmiany kolejności wyświetlanych aplikacji w zminimalizowanym zakresie.

snarshad
źródło
2
Dokładnie tak zrobiliśmy (applicationWillTerminate), ale nie sądzę, aby powiadomił o tym podczas czyszczenia pamięci, przynajmniej nie w systemie iOS 7. Zauważyłem, że powiadomienie to wyświetlało się tuż przed ponownym uruchomieniem aktualizacji systemu operacyjnego, ale tak jest rzadko to nie wyglądało tak źle.
Snarshad
„W przypadku iOS 6, jeśli zabiłeś aplikację za pomocą poruszających się ikon, nadal budziłaby się ona ponownie przy wyzwalaczach SLC. Teraz, jeśli zabijesz przez przesuwanie, tak się nie stanie”. Tak się teraz dzieje, była to tymczasowa regresja we wczesnej wersji iOS 7.
funkybro
3

To może ci pomóc

W większości przypadków system nie uruchamia ponownie aplikacji po ich wymuszonym zamknięciu przez użytkownika. Jedynym wyjątkiem są aplikacje lokalizacyjne, które w iOS 8 i nowszych są ponownie uruchamiane po wymuszonym zamknięciu przez użytkownika. W innych przypadkach użytkownik musi jednak wyraźnie uruchomić aplikację lub ponownie uruchomić urządzenie, zanim aplikacja będzie mogła automatycznie uruchomić system w tle. Gdy na urządzeniu włączona jest ochrona hasłem, system nie uruchamia aplikacji w tle przed pierwszym odblokowaniem urządzenia przez użytkownika.

Źródło: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html

Stanislav S.
źródło
3
For **iOS13**

For background PUSHES in iOS13 you must set below parameters
apns-priority = 5
apns-push-type = background
Required for WatchOS
Highly recommended for Other platforms 

PUSHES w tle Link do filmu: https://developer.apple.com/videos/play/wwdc2019/707/

CrazyPro007
źródło
Czy możesz mi udostępnić link do filmu?
guhan0