Rozwiązywanie problemów z usługami działającymi na pierwszym planie

Na tej stronie omawiamy niektóre typowe przyczyny niepowodzenia usług na pierwszym planie i pomagamy zidentyfikować przyczynę problemu.

W tym dokumencie omówiono te problemy:

Zanim zaczniesz rozwiązywać problemy

Sprawdzanie ostatnich zmian w usługach na pierwszym planie

Jeśli usługi działające na pierwszym planie są używane nieprawidłowo, mogą mieć negatywny wpływ na wydajność urządzenia i czas pracy na baterii. Z tego powodu w nowych wersjach platformy Androida często wprowadzane są zmiany w działaniu usług na pierwszym planie, aby ograniczyć te negatywne skutki.

Jeśli masz problemy z usługami działającymi na pierwszym planie, zapoznaj się z dokumentacją dotyczącą zmian w usługach działających na pierwszym planie i sprawdź, czy nie wprowadzono ostatnio zmian, które mogłyby wyjaśnić Twoje problemy. Sprawdzanie zmian jest szczególnie ważne w tych okolicznościach:

  • Kod usługi na pierwszym planie, który wcześniej działał, teraz nie działa
  • rozpoczęto testowanie nowej wersji platformy lub zmieniono poziom interfejsu API, na który jest kierowana aplikacja;

Jeśli testujesz urządzenie w wersji przedpremierowej platformy dla programistów, sprawdź najnowszą wersję dokumentacji wersji przedpremierowej dla programistów.

Błędy typu „Aplikacja nie odpowiada” (ANR)

W pewnych okolicznościach aplikacja powinna wyłączyć usługę na pierwszym planie. Jeśli aplikacja nie zatrzyma usługi, system zatrzyma ją i wywoła błąd Aplikacja nie odpowiada (ANR).

Krótka usługa działa zbyt długo, powodując błąd ANR

Usługi działające na pierwszym planie, które używają typu short service, muszą szybko zakończyć działanie, w ciągu około 3 minut. Gdy czas się skończy, system wywołuje metodę Service.onTimeout(int,int) usługi. Usługa ma kilka sekund na wywołanie stopSelf(). Jeśli usługa nie zatrzyma się sama, system wygeneruje błąd „Aplikacja nie odpowiada”.

Diagnoza:

Jeśli błąd ANR został spowodowany przez usługę na pierwszym planie, która nie zatrzymała się sama, system zgłasza wyjątek wewnętrzny. Możesz sprawdzić, czy to był problem, przeglądając raporty ANR. Jeśli to jest przyczyną problemu, w raporcie pojawi się ten komunikat:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type FOREGROUND_SERVICE_TYPE_SHORT_SERVICE did not stop within its timeout:
[component name]"

Rozwiązanie:

Upewnij się, że wszystkie usługi na pierwszym planie z ograniczonym czasem działania kończą pracę i wywołują metodę stopForeground(int) w ramach limitu czasu systemu.

Zaimplementuj Service.onTimeout(int,int) w usługach działających na pierwszym planie. Upewnij się, że implementacja tej metody od razu wywołuje funkcję stopSelf().

Wyjątki dotyczące usług na pierwszym planie

W tej sekcji opisujemy kilka problemów z usługami działającymi na pierwszym planie, które mogą powodować, że system zgłasza wyjątek. Jeśli aplikacja nie przechwyci wyjątku, użytkownik zobaczy okno z informacją, że aplikacja przestała działać.

W niektórych przypadkach system zgłasza wyjątek wewnętrzny. W takich przypadkach możesz sprawdzić, jaki to był wyjątek, w zrzucie stosu, a bardziej szczegółowe informacje o błędzie znajdziesz w Logcat.

Wyjątek wewnętrzny: przekroczono limit czasu

System nakłada limit na czas działania usług na pierwszym planie związanych z synchronizacją danych i przetwarzaniem multimediów, gdy aplikacja działa w tle. Jeśli usługa przekroczy ten limit, system wywoła metodę Service.onTimeout(int,int) usługi. Usługa ma kilka sekund na wywołanie metody stopSelf(). Jeśli usługa nie zatrzyma się sama, system wygeneruje wewnętrzny błąd RemoteServiceException, który spowoduje awarię aplikacji.

Diagnoza:

Możesz sprawdzić, jaki to był wyjątek, w zrzucie stosu, a bardziej szczegółowe informacje o błędzie znajdziesz w Logcat. W tym przypadku Logcat wyświetla taki komunikat o błędzie:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type [service type] did not stop within its timeout: [component name]"

Rozwiązanie:

Upewnij się, że wszystkie usługi na pierwszym planie z ograniczonym czasem działania kończą pracę i wywołują metodę stopForeground(int) w ramach limitu czasu systemu.

Zaimplementuj Service.onTimeout(int,int) w usługach działających na pierwszym planie. Upewnij się, że implementacja tej metody od razu wywołuje funkcję stopSelf().

Wyjątek wewnętrzny: ForegroundServiceDidNotStartInTimeException

Gdy uruchamiasz usługę, wywołując context.startForegroundService(), ma ona kilka sekund na przejście na pierwszy plan przez wywołanie ServiceCompat.startForeground(). Jeśli usługa tego nie zrobi, zostanie zgłoszony błąd wewnętrzny ForegroundServiceDidNotStartInTimeException.

Diagnoza:

Możesz sprawdzić, jaki to był wyjątek, w zrzucie stosu, a bardziej szczegółowe informacje o błędzie znajdziesz w Logcat. W tym przypadku Logcat wyświetla taki komunikat o błędzie:

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()

Rozwiązanie:

Upewnij się, że wszystkie nowo utworzone usługi na pierwszym planie wywołują metodę ServiceCompat.startForeground() w ciągu kilku sekund.

WorkManager:

Ten wyjątek może też wystąpić w przypadku instancji WorkManager, które wykonują usługę na pierwszym planie (wywołują setForegound lub setForegroundAsync). Gdy cykle życia 2 instancji na pierwszym planie nakładają się na siebie, ponieważ jedna instancja próbuje uruchomić usługę na pierwszym planie, podczas gdy wcześniej uruchomiona usługa na pierwszym planie próbuje się wyłączyć, awarii będzie towarzyszyć ten dziennik:

Re-initializing SystemForegroundService after a request to shut-down

Poprawka usuwająca tę awarię została wprowadzona w WorkManagerze w wersji 2.10.5.

Jeśli w Twojej aplikacji występuje ten wyjątek, zaktualizuj WorkManagera do najnowszej wersji i zgłoś wszelkie utrzymujące się problemy w narzędziu do śledzenia błędów WorkManagera.

ForegroundServiceStartNotAllowedException

Błąd:

System wyświetla błąd ForegroundServiceStartNotAllowedException.

Przyczyna:

Zwykle jest to spowodowane uruchomieniem przez aplikację usługi działającej na pierwszym planie, gdy aplikacja działa w tle i nie ma ważnego zwolnienia.

Począwszy od Androida 12 (poziom interfejsu API 31), aplikacje nie mogą uruchamiać usług działających na pierwszym planie, gdy aplikacja działa w tle, z kilkoma wyjątkami. Jeśli spróbujesz uruchomić usługę na pierwszym planie podczas działania w tle i nie spełnisz wymagań jednego z wyjątków, system zgłosi błąd ForegroundServiceStartNotAllowedException. System zrobi to również wtedy, gdy nie spełnisz wymagań dotyczących zwolnienia.

Na przykład aplikacja może mieć przycisk, który użytkownik może kliknąć, aby aplikacja wykonała pewne przetwarzanie, a następnie uruchomiła usługę na pierwszym planie. W takim przypadku istnieje ryzyko, że użytkownik kliknie przycisk, a następnie natychmiast przełączy aplikację w tło. Aplikacja spróbuje wtedy uruchomić usługę w tle. Jeśli aplikacja nie spełnia jednego z określonych wyjątków, system zgłasza błąd ForegroundServiceStartNotAllowedException.

Dodatkowo niektóre zwolnienia mają krótki termin ważności. Na przykład jeśli aplikacja uruchamia usługę działającą na pierwszym planie w odpowiedzi na wiadomość FCM o wysokim priorytecie, obowiązuje krótkie zwolnienie. Jeśli nie uruchomisz usługi wystarczająco szybko, otrzymasz ForegroundServiceStartNotAllowedException.

W nowych wersjach Androida niektóre wyjątki mogą być bardziej restrykcyjne. Jeśli zmienisz wersję Androida, na którą jest kierowana Twoja aplikacja, zapoznaj się z dokumentacją dotyczącą zmian w usługach na pierwszym planie i upewnij się, że aplikacja nadal spełnia warunki jednego z dozwolonych wyjątków.

Rozwiązanie:

Zmień przepływ pracy aplikacji, aby nie musiała uruchamiać usług na pierwszym planie, gdy działa w tle, lub potwierdź, że aplikacja spełnia jedno z kryteriów wyłączenia.

Możesz używać komponentów uwzględniających cykl życia do zarządzania cyklem życia aplikacji, aby nie próbować nieumyślnie uruchamiać usługi na pierwszym planie z poziomu tła.

SecurityException

Błąd:

System zgłasza błąd SecurityException.

Przyczyna:

Aplikacja próbowała uruchomić usługę na pierwszym planie bez wymaganych uprawnień.

  • Jeśli aplikacja jest kierowana na Androida 9 (API na poziomie 28) lub nowszego, musi mieć uprawnienie FOREGROUND_SERVICE, aby uruchomić usługę na pierwszym planie.
  • Jeśli aplikacja jest kierowana na Androida 14 (API na poziomie 34) lub nowszego, musi spełniać wszystkie wymagania wstępne dotyczące typu usługi działającej na pierwszym planie. Te wymagania wstępne są szczegółowo opisane w dokumentacji dotyczącej typów usług na pierwszym planie. Zwróć szczególną uwagę na te wymagania:
    • Kilka typów usług na pierwszym planie wymaga określonych uprawnień w czasie działania. Na przykład usługa zdalnego przesyłania wiadomości na pierwszym planie musi mieć uprawnienie FOREGROUND_SERVICE_REMOTE_MESSAGING.
  • W niektórych przypadkach obowiązują dodatkowe ograniczenia dotyczące uprawnień wymaganych przez niektóre typy usług na pierwszym planie, gdy aplikacja jest używana. Te uprawnienia są przyznawane aplikacji tylko wtedy, gdy jest ona na pierwszym planie (z kilkoma wyjątkami). Oznacza to, że nawet jeśli aplikacja poprosiła o jedno z tych uprawnień i je otrzymała, to gdy spróbuje uruchomić usługę na pierwszym planie, działając w tle, system wygeneruje błąd SecurityException, nawet jeśli aplikacja jest zwolniona z obowiązku uruchamiania usługi na pierwszym planie z poziomu tła. Więcej informacji znajdziesz w sekcji Ograniczenia dotyczące uruchamiania usług działających na pierwszym planie, które wymagają uprawnień podczas używania.
    • Jeśli poprosisz o wymagane uprawnienia, ale uruchomisz usługę na pierwszym planie, zanim potwierdzisz, że zostały one przyznane, może pojawić się błąd SecurityException.

Rozwiązanie:

Zanim uruchomisz usługę działającą na pierwszym planie, poproś o wszystkie odpowiednie uprawnienia dla takiej usługi i upewnij się, że spełniasz wszystkie inne wymagania wstępne dotyczące środowiska wykonawczego.