Usługi działające na pierwszym planie wykonują operacje zauważalne dla użytkownika.
Usługi na pierwszym planie wyświetlają powiadomienie na pasku stanu, aby poinformować użytkowników, że aplikacja wykonuje zadanie na pierwszym planie i korzysta z zasobów systemu.
Przykłady aplikacji, które korzystają z usług na pierwszym planie:
- Aplikacja odtwarzająca muzykę, która działa na pierwszym planie. Powiadomienie może wyświetlać aktualnie odtwarzany utwór.
- Aplikacja fitness, która rejestruje bieg użytkownika w usłudze na pierwszym planie, po otrzymaniu zgody użytkownika. Powiadomienie może zawierać informację o przebytej przez użytkownika odległości podczas bieżącej sesji fitness.
Usługi na pierwszym planie używaj tylko wtedy, gdy aplikacja musi wykonać zadanie, które jest zauważalne dla użytkownika, nawet gdy nie wchodzi on z nią w bezpośrednią interakcję. Jeśli działanie jest na tyle mało istotne, że chcesz użyć powiadomienia o minimalnym priorytecie, utwórz zamiast tego zadania działającego w tle.
W tym dokumencie opisujemy wymagane uprawnienia do korzystania z usług na pierwszym planie oraz sposób uruchamiania i usuwania usług na pierwszym planie z tła. Zawiera ona też informacje o tym, jak powiązać określone przypadki użycia z typami usług na pierwszym planie, oraz o ograniczeniach dostępu, które wchodzą w życie, gdy uruchomisz usługę na pierwszym planie z aplikacji działającej w tle.
Użytkownik może domyślnie zamknąć powiadomienie
Od Androida 13 (poziom interfejsu API 33) użytkownicy mogą domyślnie zamykać powiadomienia powiązane z usługą na pierwszym planie. Aby to zrobić, użytkownicy muszą przesunąć palcem po powiadomieniu. Zazwyczaj powiadomienie nie znika, dopóki usługa działająca na pierwszym planie nie zostanie zatrzymana lub usunięta z pierwszego planu.
Jeśli chcesz, aby powiadomienie nie mogło zostać zamknięte przez użytkownika, przekaż parametr true
do metody setOngoing()
podczas tworzenia powiadomienia za pomocą funkcji Notification.Builder
.
Usługi, które wyświetlają powiadomienie natychmiast
Jeśli usługa na pierwszym planie ma co najmniej jedną z tych cech, system wyświetla powiązane powiadomienie natychmiast po uruchomieniu usługi, nawet na urządzeniach z Androidem 12 lub nowszym:
- Usługa jest powiązana z powiadomieniem, które zawiera przyciski poleceń.
- Usługa ma
foregroundServiceType
mediaPlayback
,mediaProjection
lubphoneCall
. - Usługa zapewnia przypadki użycia związane z połączeniami telefonicznymi, nawigacją lub odtwarzaniem multimediów, zgodnie z definicją w atrybutze kategorii powiadomienia.
- Usługa zrezygnowała ze zmiany zachowania, przekazując
FOREGROUND_SERVICE_IMMEDIATE
dosetForegroundServiceBehavior()
podczas konfigurowania powiadomienia.
W Androidzie 13 (API na poziomie 33) lub nowszym, jeśli użytkownik odmówi wydania uprawnień do powiadomień, nadal będzie widzieć powiadomienia dotyczące usług na pierwszym planie w Menedżerze zadań, ale nie zobaczy ich w szufladzie powiadomień.
Deklarowanie usług na pierwszym planie w pliku manifestu
W pliku manifestu aplikacji zadeklaruj każdą usługę na pierwszym planie za pomocą elementu <service>
. W przypadku każdej usługi użyj atrybutu android:foregroundServiceType
, aby określić, jakie zadania wykonuje usługa.
Jeśli na przykład Twoja aplikacja tworzy usługę na pierwszym planie, która odtwarza muzykę, możesz zadeklarować ją w ten sposób:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<application ...>
<service
android:name=".MyMediaPlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="false">
</service>
</application>
</manifest>
Jeśli do usługi stosuje się kilka typów, rozdziel je operatorem |
. Na przykład usługa, która korzysta z kamery i mikrofonu, mogłaby być zadeklarowana w ten sposób:
android:foregroundServiceType="camera|microphone"
Proś o uprawnienia usługi działającej na pierwszym planie
Aplikacje przeznaczone na Androida 9 (poziom interfejsu API 28) lub nowszego i korzystające z usług na pierwszym planie muszą w pliku manifestu aplikacji poprosić o FOREGROUND_SERVICE
, jak pokazano w tym fragmencie kodu. Jest to normalne uprawnienie, więc system automatycznie przyznaje je aplikacji, która o nie prosi.
Jeśli aplikacja jest kierowana na interfejs API na poziomie 34 lub wyższym, musi poprosić o odpowiednie uprawnienia do wykonywania zadań przez usługę na pierwszym planie. Każdy typ usługi na pierwszym planie ma odpowiadający mu typ uprawnienia. Jeśli na przykład aplikacja uruchamia usługę na pierwszym planie, która korzysta z aparatu, musisz poprosić o uprawnienia FOREGROUND_SERVICE
i FOREGROUND_SERVICE_CAMERA
. To są wszystkie zwykłe uprawnienia, więc system przyznaje je automatycznie, jeśli są wymienione w pliku manifestu.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
<application ...>
...
</application>
</manifest>
Wymagania wstępne usługi działającej na pierwszym planie
Od Androida 14 (poziom interfejsu API 34) podczas uruchamiania usługi na pierwszym planie system sprawdza określone wymagania w zależności od typu usługi. Jeśli na przykład spróbujesz uruchomić usługę na pierwszym planie typu location
, system sprawdzi, czy Twoja aplikacja ma już uprawnienie ACCESS_COARSE_LOCATION
lub ACCESS_FINE_LOCATION
. Jeśli nie, system zgłosi błądSecurityException
.
Dlatego przed uruchomieniem usługi na pierwszym planie musisz sprawdzić, czy są spełnione wymagania wstępne. Dokumentacja typu usługi na pierwszym planie zawiera wymagane warunki wstępne dla każdego typu usługi na pierwszym planie.
Uruchamianie usługi na pierwszym planie
Zanim poprosisz system o uruchomienie usługi jako usługi na pierwszym planie, uruchom tę usługę:
Kotlin
val intent = Intent(...) // Build the intent for the service context.startForegroundService(intent)
Java
Context context = getApplicationContext(); Intent intent = new Intent(...); // Build the intent for the service context.startForegroundService(intent);
W usłudze, zwykle w funkcji onStartCommand()
, możesz poprosić o uruchomienie usługi na pierwszym planie. Aby to zrobić, wywołaj funkcję ServiceCompat.startForeground()
(dostępną w wersji androidx-core 1.12 lub nowszej). Ta metoda przyjmuje te parametry:
- Usługa
- dodatnia liczba całkowita, która jednoznacznie identyfikuje powiadomienie na pasku stanu;
- Obiekt
Notification
- Typy usług działających na pierwszym planie:
W zależności od konkretnego przypadku użycia te typy mogą być podzbiorem typów zadeklarowanych w pliku manifestu. Jeśli chcesz dodać więcej typów usług, możesz ponownie zadzwonić do startForeground()
.
Załóżmy na przykład, że aplikacja fitness uruchamia usługę śledzenia biegania, która zawsze potrzebuje informacji location
, ale może lub nie musi odtwarzać multimediów. W pliku manifestu musisz zadeklarować zarówno location
, jak i mediaPlayback
. Jeśli użytkownik rozpocznie bieg i chce, aby aplikacja śledziła jego lokalizację, aplikacja powinna wywołać funkcję startForeground()
i przekazać tylko uprawnienie ACCESS_FINE_LOCATION
. Następnie, jeśli użytkownik chce rozpocząć odtwarzanie dźwięku, wywołaj ponownie funkcję startForeground()
, przekazując kombinację bitową wszystkich typów usług na pierwszym planie (w tym przypadku ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
).
Oto przykład uruchamiania usługi działającej na pierwszym planie w aparacie:
Kotlin
class MyCameraService: Service() { private fun startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user has // granted the CAMERA permission. val cameraPermission = PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA) if (cameraPermission != PermissionChecker.PERMISSION_GRANTED) { // Without camera permissions the service cannot run in the foreground // Consider informing user or updating your app UI if visible. stopSelf() return } try { val notification = NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service is running .build() ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA } else { 0 }, ) } catch (e: Exception) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e is ForegroundServiceStartNotAllowedException) { // App not in a valid state to start foreground service // (e.g. started from bg) } // ... } } }
Java
public class MyCameraService extends Service { private void startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user // has granted the CAMERA permission. int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); if (cameraPermission == PackageManager.PERMISSION_DENIED) { // Without camera permissions the service cannot run in the // foreground. Consider informing user or updating your app UI if // visible. stopSelf(); return; } try { Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service // is running .build(); int type = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { type = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; } ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ type ); } catch (Exception e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e instanceof ForegroundServiceStartNotAllowedException ) { // App not in a valid state to start foreground service // (e.g started from bg) } // ... } } //... }
Usuwanie usługi z pierwszego planu
Aby usunąć usługę z pierwszego planu, zadzwoń do stopForeground()
.
Ta metoda przyjmuje wartość logiczną, która wskazuje, czy należy usunąć także powiadomienie na pasku stanu. Pamiętaj, że usługa nadal działa.
Jeśli usługa jest uruchomiona na pierwszym planie, a Ty ją zatrzymasz, powiadomienie o niej zostanie usunięte.
Obsługa zatrzymywania przez użytkownika aplikacji uruchamiających usługi na pierwszym planie
Od Androida 13 (poziom interfejsu API 33) użytkownicy mogą kończyć procesy w schowalni powiadomień, aby zatrzymać aplikację, która ma aktywne usługi na pierwszym planie, niezależnie od wersji docelowego pakietu SDK tej aplikacji. Ta funkcja, zwana Menedżerem zadań, wyświetla listę aplikacji, które obecnie uruchamiają usługę na pierwszym planie.
Ta lista ma etykietę Aktywne aplikacje. Obok każdej aplikacji znajduje się przycisk Zatrzymaj. Rysunek 1 przedstawia proces zarządzania zadaniami na urządzeniu z Androidem 13.
Gdy użytkownik naciśnie przycisk Zatrzymaj obok aplikacji w Menedżerze zadań, nastąpią następujące działania:
- System usuwa aplikację z pamięci. W rezultacie cała aplikacja się zatrzymuje, a nie tylko uruchomiona usługa na pierwszym planie.
- System usuwa z aplikacji stos aktywności.
- Zatrzymuje się odtwarzanie multimediów.
- Powiadomienie powiązane z usługą na pierwszym planie zostanie usunięte.
- Aplikacja pozostanie w historii.
- Zaplanowane zadania są wykonywane w wyznaczonym czasie.
- Alarmy włączają się o zaplanowanym czasie lub w określonym przedziale czasowym.
Aby sprawdzić, czy aplikacja zachowuje się zgodnie z oczekiwaniami, gdy użytkownik ją zatrzymuje, uruchom w oknie terminala to polecenie ADB:
adb shell cmd activity stop-app PACKAGE_NAME
Wyjątki
System przewiduje kilka poziomów wyjątków w przypadku niektórych typów aplikacji, co jest opisane w następnych sekcjach.
Wyjątki dotyczą aplikacji, a nie procesów. Jeśli system zwalnia z ochrony jeden proces w aplikacji, zwalnia z ochrony wszystkie procesy w tej aplikacji.
Wyjątki dotyczące wyświetlania w Menedżerze zadań
Poniższe aplikacje mogą uruchamiać usługę na pierwszym planie i w ogóle nie wyświetlać się w Menedżerze zadań:
- Aplikacje na poziomie systemu
- aplikacje bezpieczeństwa, czyli aplikacje z rolą
ROLE_EMERGENCY
; - Urządzenia w trybie demonstracyjnym
Wyjątki od możliwości zatrzymania przez użytkowników
Gdy aplikacje z tych typów uruchamiają usługę na pierwszym planie, są widoczne w Menedżerze zadań, ale obok nazwy aplikacji nie ma przycisku Zatrzymaj, który użytkownik mógłby kliknąć:
- Aplikacje właściciela urządzenia
- Właściciel profilu aplikacje
- Aplikacje trwałe
- Aplikacje z rolą
ROLE_DIALER
Zamiast usług na pierwszym planie używaj interfejsów API do określonych celów
W przypadku wielu zastosowań istnieją interfejsy API platformy lub Jetpacka, których możesz używać do wykonywania zadań, do których w przeciwnym razie używasz usługi na pierwszym planie. Jeśli istnieje odpowiedni interfejs API, który został stworzony do określonego celu, prawie zawsze należy z niego korzystać zamiast usługi na pierwszym planie. Specjalnie zaprojektowane interfejsy API często zapewniają dodatkowe funkcje, które w przeciwnym razie musiałbyś tworzyć samodzielnie. Na przykład interfejs Bubbles API obsługuje złożoną logikę interfejsu użytkownika w przypadku aplikacji do obsługi wiadomości, które muszą implementować funkcje okienka czatu.
Dokumentacja dotycząca typów usług na pierwszym planie zawiera listę odpowiednich alternatyw dla usług na pierwszym planie.
Ograniczenia dotyczące uruchamiania usługi na pierwszym planie w tle
Aplikacje kierowane na Androida 12 lub nowszego nie mogą uruchamiać usług na pierwszym planie, gdy aplikacja działa w tle, z wyjątkiem kilku szczególnych przypadków. Jeśli aplikacja próbuje uruchomić usługę na pierwszym planie, gdy sama działa w tle, a usługa na pierwszym planie nie spełnia jednego z wyjątków, system zgłasza błąd ForegroundServiceStartNotAllowedException
.
Jeśli aplikacja chce uruchomić usługę na pierwszym planie, która wymaga uprawnień w trakcie korzystania (np. uprawnień do korzystania z ciała, aparatu, mikrofonu lub lokalizacji), nie może tworzyć tej usługi, gdy działa w tle, nawet jeśli kwalifikuje się do jednej z wyjątków od ograniczeń uruchamiania w tle. Wyjaśnienie tego powodu znajdziesz w sekcji Ograniczenia uruchamiania usług na pierwszym planie, które wymagają uprawnień podczas korzystania.
Wyjątki od ograniczeń dotyczących uruchamiania w tle
W tych sytuacjach aplikacja może uruchamiać usługi na pierwszym planie, nawet gdy sama działa w tle:
- aplikacja przechodzi ze stanu widocznego dla użytkownika, np. aktywności;
- Aplikacja może rozpocząć działanie w tle, z wyjątkiem sytuacji, gdy ma ona aktywność w stosie poprzednich zadań.
Twoja aplikacja otrzymuje wiadomość o wysokim priorytecie za pomocą Komunikacji w chmurze Firebase.
Użytkownik wykonuje działanie związane z elementem UI w Twojej aplikacji. Może na przykład wejść w interakcję z bąbelkiem, powiadomieniem, widżetem lub aktywnością.
Aplikacja wywołuje alarm precyzyjny, aby wykonać działanie, o które prosi użytkownik.
Aplikacja jest bieżącą metodą wprowadzania danych na urządzeniu.
Aplikacja otrzymuje zdarzenie związane z geofencingiem lub przejściem do trybu rozpoznawania aktywności.
Gdy urządzenie się uruchomi ponownie i odbierze działanie
ACTION_BOOT_COMPLETED
,ACTION_LOCKED_BOOT_COMPLETED
lubACTION_MY_PACKAGE_REPLACED
, działanie o zawartości w odbiorniku transmisji.Twoja aplikacja otrzymuje działanie intencyjne
ACTION_TIMEZONE_CHANGED
,ACTION_TIME_CHANGED
lubACTION_LOCALE_CHANGED
w odbiorniku.Twoja aplikacja odbiera zdarzenie
ACTION_TRANSACTION_DETECTED
zNfcService
.Aplikacje z określonymi rolami systemowymi lub uprawnieniami, takie jak właściciele urządzenia i właściciele profilu.
Aplikacja korzysta z Menedżera urządzeń towarzyszących i deklaruje uprawnienie
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
lub uprawnienieREQUEST_COMPANION_RUN_IN_BACKGROUND
. W miarę możliwości używaj taguREQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
.Użytkownik wyłącza optymalizację baterii w Twojej aplikacji.
Twoja aplikacja ma uprawnienie
SYSTEM_ALERT_WINDOW
. Uwaga: jeśli Twoja aplikacja jest kierowana na Androida 15 lub nowszego, musi mieć uprawnienieSYSTEM_ALERT_WINDOW
i musi mieć obecnie widoczne okno nakładki.
Ograniczenia dotyczące uruchamiania usług na pierwszym planie, które wymagają uprawnień podczas korzystania
W Androidzie 14 (poziom API 34) lub nowszym występują specjalne sytuacje, o których musisz pamiętać, gdy uruchamiasz usługę na pierwszym planie, która wymaga uprawnień podczas korzystania.
Jeśli Twoja aplikacja jest kierowana na Androida 14 lub nowszą wersję, podczas tworzenia usługi na pierwszym planie system operacyjny sprawdza, czy aplikacja ma wszystkie odpowiednie uprawnienia dla tego typu usługi. Gdy na przykład utworzysz usługę na pierwszym planie typu mikrofon, system operacyjny sprawdzi, czy Twoja aplikacja ma aktualnie uprawnienie RECORD_AUDIO
. Jeśli nie masz tego uprawnienia, system wyświetli komunikat
SecurityException
.
W przypadku uprawnień do korzystania z usług może to spowodować problem. Jeśli aplikacja ma uprawnienia „podczas używania”, ma je tylko podczas działania na pierwszym planie. Oznacza to, że jeśli aplikacja działa w tle i próbuje utworzyć usługę na pierwszym planie typu kamera, lokalizacja lub mikrofon, system stwierdza, że aplikacja obecnie nie ma wymaganych uprawnień, i wyrzuca błądSecurityException
.
Podobnie, jeśli aplikacja działa w tle i tworzy usługę medyczną, która wymaga uprawnienia BODY_SENSORS
, a aplikacja nie ma tego uprawnienia, system zgłasza wyjątek.
(Nie dotyczy to usług medycznych, które wymagają innych uprawnień, takich jak ACTIVITY_RECOGNITION
). Nawet wywołanie funkcji PermissionChecker.checkSelfPermission()
nie nie zapobiegnie temu problemowi. Jeśli aplikacja ma uprawnienia podczas korzystania i wywołuje metodę checkSelfPermission()
, aby sprawdzić, czy ma te uprawnienia, metoda zwraca PERMISSION_GRANTED
, nawet jeśli aplikacja działa w tle. Gdy metoda zwraca wartość PERMISSION_GRANTED
, oznacza to, że „Twoja aplikacja ma to uprawnienie podczas używania aplikacji”.
Jeśli więc usługa na pierwszym planie potrzebuje uprawnienia „podczas używania”, musisz wywołać funkcję Context.startForegroundService()
lub Context.bindService()
, gdy aplikacja ma widoczną aktywność, chyba że usługa kwalifikuje się do jednej z określonych wyjątków.
Wyjątki od ograniczeń dotyczących uprawnień podczas korzystania
W niektórych sytuacjach nawet wtedy, gdy usługa na pierwszym planie jest uruchomiona, gdy aplikacja działa w tle, może ona nadal uzyskiwać informacje o lokalizacji, kamerze i mikrofonie, gdy aplikacja działa na pierwszym planie („podczas używania”).
W tych samych sytuacjach, jeśli usługa deklaruje typ usługi na pierwszym planie location
i jest uruchamiana przez aplikację, która ma uprawnienie ACCESS_BACKGROUND_LOCATION
, usługa ta może mieć dostęp do informacji o lokalizacji przez cały czas, nawet gdy aplikacja działa w tle.
Poniżej znajdziesz listę takich sytuacji:
- Usługę uruchamia komponent systemu.
- Usługa zaczyna się od interakcji z widżetami aplikacji.
- Usługa rozpoczyna się od interakcji z powiadomieniem.
- Usługa rozpoczyna się jako
PendingIntent
wysyłana z innej widocznej aplikacji. - Usługa uruchamia aplikację, która jest kontrolerem zasad urządzeń i działa w trybie właściciela urządzenia.
- Usługa jest uruchamiana przez aplikację, która zapewnia
VoiceInteractionService
. - Usługa jest uruchamiana przez aplikację, która ma uprawnienia
START_ACTIVITIES_FROM_BACKGROUND
.
Określanie usług, których dotyczy problem w aplikacji
Podczas testowania aplikacji uruchom jej usługi działające na pierwszym planie. Jeśli uruchomiona usługa ma ograniczony dostęp do lokalizacji, mikrofonu i kamery, w Logcat pojawi się ten komunikat:
Foreground service started from background can not have \ location/camera/microphone access: service SERVICE_NAME