Aplikacje często muszą wykonywać więcej niż 1 czynność naraz. Interfejsy API Androida oferują wiele różnych sposobów na to. Wybór odpowiedniej opcji jest bardzo ważny. Jedna opcja może być odpowiednia w jednej sytuacji, ale bardzo zła w innej. Wybór nieodpowiednich interfejsów API może obniżyć wydajność aplikacji lub efektywność wykorzystania zasobów, co może wyczerpywać baterię i obniżać wydajność urządzenia użytkownika jako całości. W niektórych przypadkach wybór niewłaściwego podejścia może uniemożliwić zamieszczenie aplikacji w Sklepie Play.
W tym dokumencie opisujemy różne dostępne opcje i pomagamy wybrać tę, która jest odpowiednia w Twojej sytuacji.
Terminologia
Niektóre ważne terminy związane z zadaniami w tle mogą być używane na różne, sprzeczne sposoby. Dlatego ważne jest, aby zdefiniować nasze warunki.
Jeśli aplikacja działa w tle, system nakłada na nią pewne ograniczenia. (na przykład w większości przypadków aplikacja działająca w tle nie może uruchamiać usług na pierwszym planie).
W tym dokumencie używamy terminu „zadania” w odniesieniu do operacji wykonywanych przez aplikację poza jej głównym przepływem pracy. Aby ułatwić Ci zrozumienie tych pojęć, podzieliliśmy zadania na 3 główne kategorie: praca asynchroniczna, interfejsy API do planowania zadań i usługi na pierwszym planie.
Wybierz odpowiednią opcję
W większości przypadków odpowiednie interfejsy API do wykonania zadania możesz znaleźć, określając kategorię (praca asynchroniczna, interfejsy API do planowania zadań lub usługi na pierwszym planie), do której należy dane zadanie.
Jeśli nadal nie masz pewności, możesz skorzystać z dostępnych schematów, które pomogą Ci podjąć decyzję. Każdą z tych opcji omówimy bardziej szczegółowo w dalszej części tego dokumentu.
W przypadku zadań w tle należy wziąć pod uwagę 2 główne scenariusze:
- Zadanie zainicjowane przez użytkownika, gdy aplikacja jest widoczna
- Zadanie jest inicjowane w odpowiedzi na zdarzenie wewnętrzne lub zewnętrzne
Oba te scenariusze mają własne drzewa decyzji.
Praca asynchroniczna
W wielu przypadkach aplikacja musi wykonywać operacje równolegle, gdy działa na pierwszym planie. Aplikacja może na przykład potrzebować czasu na wykonanie obliczeń. Jeśli obliczenia byłyby wykonywane w wątku interfejsu użytkownika, użytkownik nie mógłby korzystać z aplikacji, dopóki nie zakończyłyby się obliczenia. Mogłoby to spowodować błąd ANR. W takim przypadku aplikacja powinna korzystać z opcji pracy asynchronicznej.
Typowe opcje pracy asynchronicznej to coroutines w Kotlinie i wątki w Javie. Więcej informacji znajdziesz w dokumentacji dotyczącej pracy asynchronicznej. Pamiętaj, że w odróżnieniu od interfejsów API zadań w tle asynchroniczne działanie nie jest gwarantowane, jeśli aplikacja przestaje znajdować się w obowiązującej fazie cyklu życia (np. jeśli aplikacja przestaje być widoczna na pierwszym planie).
Interfejsy API do planowania zadań
Interfejsy API do planowania zadań to bardziej elastyczna opcja, gdy trzeba wykonywać zadania, które muszą być kontynuowane nawet wtedy, gdy użytkownik opuści aplikację. W większości przypadków najlepszym rozwiązaniem do wykonywania zadań w tle jest użycie interfejsu WorkManager, ale w niektórych przypadkach może być konieczne użycie interfejsu platformy JobScheduler
.
WorkManager to zaawansowana biblioteka, która umożliwia konfigurowanie prostych i skomplikowanych zadań. Za pomocą WorkManagera możesz zaplanować uruchamianie zadań w określonych momentach lub określić warunki ich uruchamiania. Możesz nawet tworzyć łańcuchy zadań, które będą wykonywane kolejno, przekazując wyniki jednego zadania do następnego. Aby poznać wszystkie dostępne opcje, zapoznaj się z listą funkcji WorkManager.
Oto kilka najczęstszych scenariuszy zadań wykonywanych w tle:
- okresowe pobieranie danych z serwera,
- Pobieranie danych z czujników (np. danych z licznika kroków)
- okresowe pobieranie danych o lokalizacji (w Androidzie 10 lub nowszym musisz mieć przyznane uprawnienie
ACCESS_BACKGROUND_LOCATION
); - przesyłanie treści na podstawie wyzwalacza treści, takiego jak zdjęcia wykonane przez aparat;
Usługi działające na pierwszym planie
Usługi na pierwszym planie to skuteczny sposób na natychmiastowe wykonywanie zadań, które nie powinny być przerywane. Usługi na pierwszym planie mogą jednak obciążać urządzenie, a czasami mają wpływ na prywatność i bezpieczeństwo. Z tego powodu system nakłada wiele ograniczeń na sposób i czas korzystania przez aplikacje z usług na pierwszym planie. Na przykład usługa na pierwszym planie musi być zauważalna dla użytkownika. W większości przypadków aplikacje nie mogą uruchamiać usług na pierwszym planie, gdy są w tle. Więcej informacji znajdziesz w dokumentacji usług na pierwszym planie.
Usługę na pierwszym planie można utworzyć na 2 sposoby. Możesz zadeklarować własną Service
i określić, że jest to usługa działająca na pierwszym planie, wywołując Service.startForeground()
. Możesz też użyć WorkManagera do utworzenia usługi na pierwszym planie, jak opisano w artykule Wsparcie dla długotrwałych wątków.
Należy jednak pamiętać, że usługa na pierwszym planie utworzona przez WorkManager musi być zgodna ze wszystkimi tymi samymi ograniczeniami co inne usługi na pierwszym planie.
WorkManager udostępnia tylko kilka wygodnych interfejsów API, które ułatwiają tworzenie usługi na pierwszym planie.
Alternatywny interfejs API
System oferuje alternatywne interfejsy API, które są lepiej dostosowane do konkretnych zastosowań. Jeśli w Twoim przypadku istnieje alternatywny interfejs API, zalecamy użycie go zamiast usługi na pierwszym planie, ponieważ może to poprawić działanie aplikacji. Dokumentacja typów usług na pierwszym planie zawiera informacje o tym, kiedy można użyć alternatywnego interfejsu API zamiast konkretnego typu usługi na pierwszym planie.
Oto niektóre z najczęstszych scenariuszy użycia alternatywnych interfejsów API:
- korzystania z przesyłania danych inicjowanych przez użytkownika do wykonywania dużych pobrań lub przesyłania, zamiast tworzenia usługi na pierwszym planie do synchronizacji danych;
- Korzystanie z menedżera urządzenia towarzyszącego do parowania i przesyłania danych przez Bluetooth zamiast korzystania z połączonego urządzenia jako usługi na pierwszym planie
- Korzystanie z trybu obrazu w obrazie do odtwarzania filmów zamiast tworzenia usługi odtwarzania multimediów na pierwszym planie.
Zadania inicjowane przez użytkownika
Jeśli aplikacja musi wykonywać zadania w tle, a użytkownik inicjuje tę operację, gdy aplikacja jest widoczna, odpowiedz na te pytania, aby znaleźć właściwe podejście.
Czy zadanie musi być wykonywane, gdy aplikacja działa w tle?
Jeśli zadanie nie musi być wykonywane, gdy aplikacja działa w tle, użyj pracy asynchronicznej. Istnieje wiele opcji pracy asynchronicznej. Pamiętaj, że te opcje przestają działać, gdy aplikacja przechodzi w stan w tle. (przestają też działać, gdy aplikacja zostanie zamknięta). Na przykład aplikacja społecznościowa może chcieć odświeżyć kanał treści, ale nie musi kończyć operacji, jeśli użytkownik opuścił ekran.
Czy użytkownicy będą niezadowoleni, jeśli zadanie zostanie odroczone lub przerwane?
Należy wziąć pod uwagę, czy w przypadku opóźnienia lub anulowania zadania wrażenia użytkownika nie ulegną pogorszeniu. Jeśli na przykład aplikacja musi zaktualizować swoje zasoby, użytkownik może nie zauważyć, czy operacja odbywa się natychmiast, czy w środku nocy, gdy urządzenie się ładuje. W takich przypadkach należy użyć opcji pracy w tle.
Czy to krótkie, krytyczne zadanie?
Jeśli zadanie nie może zostać opóźnione i zostanie wykonane szybko, możesz użyć usługi na pierwszym planie z typem shortService
. Te usługi są łatwiejsze do utworzenia niż inne usługi na pierwszym planie i nie wymagają tylu uprawnień. Krótkie usługi muszą jednak zostać wykonane w ciągu 3 minut.
Czy istnieje inny interfejs API przeznaczony tylko do tego celu?
Jeśli zadanie nie jest niewidoczne dla użytkownika, odpowiednim rozwiązaniem może być użycie usługi na pierwszym planie. Te usługi działają nieprzerwanie po uruchomieniu, więc są dobrym wyborem, gdy przerwanie zadania wiązałoby się z niedogodnościami dla użytkownika. Na przykład aplikacja do śledzenia treningów może używać czujników lokalizacji, aby umożliwić użytkownikom rejestrowanie trasy biegu na mapie. Nie zalecamy korzystania z opcji działania w tle, ponieważ w przypadku wstrzymania zadania śledzenie zostanie natychmiast przerwane. W takim przypadku użycie usługi na pierwszym planie jest najbardziej uzasadnione.
Ponieważ jednak usługi na pierwszym planie mogą potencjalnie korzystać z dużej ilości zasobów urządzenia, system nakłada wiele ograniczeń dotyczących tego, kiedy i jak można z nich korzystać. W wielu przypadkach zamiast usługi na pierwszym planie możesz użyć alternatywnego interfejsu API, który wykona zadanie bez większych problemów. Jeśli na przykład aplikacja ma wykonać działanie, gdy użytkownik dotrze do określonej lokalizacji, najlepszym rozwiązaniem jest użycie interfejsu API do obsługi geoogrodzenia zamiast śledzenia lokalizacji użytkownika za pomocą usługi na pierwszym planie.
Zadania wykonywane w odpowiedzi na zdarzenie
Czasami aplikacja musi wykonywać zadania w tle w odpowiedzi na określony czynnik, np.:
- Komunikaty
- Wiadomości Komunikacji w chmurze Firebase (FCM)
- Alarmy ustawione przez aplikację.
Może to być zewnętrzny wyzwalacz (np. wiadomość FCM) lub reakcja na alarm ustawiony przez aplikację. Gra może na przykład otrzymać wiadomość FCM z prośbą o zaktualizowanie niektórych komponentów.
Jeśli masz pewność, że zadanie zostanie ukończone w kilka sekund, wykonaj je za pomocą pracy asynchronicznej. System przyzna aplikacji kilka sekund na wykonanie takich zadań, nawet jeśli aplikacja działała w tle.
Jeśli zadanie będzie wymagać więcej niż kilku sekund, może być konieczne uruchomienie usługi na pierwszym planie. Nawet jeśli aplikacja jest obecnie uruchomiona w tle, może mieć możliwość uruchomienia usługi na pierwszym planie, jeśli zadanie zostało wywołane przez użytkownika i wchodzi w ramy jednej z zatwierdzonych wyjątków od ograniczeń uruchamiania w tle. Jeśli na przykład aplikacja otrzyma wiadomość FCM o wysokim priorytecie, może uruchomić usługę na pierwszym planie, nawet jeśli sama działa w tle.
Jeśli zadanie zajmie więcej niż kilka sekund, użyj interfejsów API do planowania zadań.