Uruchomienie usługi na pierwszym planie z poziomu aplikacji wymaga wykonania 2 czynności. Najpierw musisz uruchomić usługę, wywołując metodę
context.startForegroundService(). Następnie usługa musi wywołać metodę ServiceCompat.startForeground(), aby przejść do działania na pierwszym planie.
Wymagania wstępne
W zależności od poziomu interfejsu API, na który jest kierowana aplikacja, obowiązują pewne ograniczenia dotyczące tego, kiedy aplikacja może uruchomić usługę na pierwszym planie.
Aplikacje kierowane na Androida 12 (poziom interfejsu API 31) lub nowszego nie mogą uruchamiać usługi na pierwszym planie, gdy aplikacja działa w tle, z kilkoma wyjątkami. Więcej informacji i informacje o wyjątkach od tej reguły znajdziesz w artykule Ograniczenia dotyczące uruchamiania usługi na pierwszym planie w tle.
Aplikacje kierowane na Androida 14 (poziom interfejsu API 34) lub nowszego muszą poprosić o odpowiednie uprawnienia dla typu usługi na pierwszym planie. Gdy aplikacja próbuje przenieść usługę na pierwszy plan, system sprawdza odpowiednie uprawnienia i zgłasza wyjątek
SecurityException, jeśli aplikacja nie ma żadnych uprawnień. Jeśli na przykład spróbujesz uruchomić usługę na pierwszym planie typulocation, system sprawdzi, czy Twoja aplikacja ma już uprawnienieACCESS_COARSE_LOCATIONlubACCESS_FINE_LOCATION. W dokumentacji typu usługi na pierwszym planie znajdziesz listę wymaganych warunków wstępnych dla każdego typu usługi na pierwszym planie.
Uruchamianie usługi
Aby uruchomić usługę na pierwszym planie, musisz najpierw uruchomić ją jako zwykłą usługę (nie na pierwszym planie):
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);
Najważniejsze informacje o kodzie
- Ten fragment kodu uruchamia usługę. Usługa nie działa jednak jeszcze na pierwszym planie. W samej usłudze musisz wywołać metodę
ServiceCompat.startForeground(), aby przenieść usługę na pierwszy plan.
Przenoszenie usługi na pierwszy plan
Gdy usługa jest uruchomiona, musisz wywołać
ServiceCompat.startForeground(), aby poprosić o uruchomienie usługi
na pierwszym planie. Zwykle wywołujesz tę metodę w metodzie
onStartCommand() usługi.
Metoda ServiceCompat.startForeground() przyjmuje te parametry:
- Usługa.
- Dodatnia liczba całkowita, która jednoznacznie identyfikuje powiadomienie usługi na pasku stanu.
- Sam obiekt
Notification. - Typ lub typy usług na pierwszym planie, które identyfikują pracę wykonywaną przez usługę.
Typy usług na pierwszym planie, które przekazujesz do startForeground()
metody `startForeground()`, muszą być zgodne z typami zadeklarowanymi w pliku manifestu, w zależności od konkretnego
przypadku użycia. Jeśli chcesz dodać więcej typów usług, możesz ponownie wywołać metodę startForeground().
Załóżmy na przykład, że aplikacja treningowa uruchamia usługę śledzenia biegu, która zawsze potrzebuje informacji o location, ale może, ale nie musi odtwarzać multimediów. W pliku manifestu musisz zadeklarować zarówno location, jak i mediaPlayback. Jeśli użytkownik zacznie biec i chce tylko śledzić swoją lokalizację, Twoja aplikacja powinna wywołać metodę startForeground() i przekazać tylko uprawnienie ACCESS_FINE_LOCATION. Jeśli użytkownik chce zacząć odtwarzać dźwięk, ponownie wywołaj metodę startForeground() i przekaż bitową kombinację wszystkich typów usług na pierwszym planie (w tym przypadku ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK).
Poniższy przykład pokazuje kod, którego usługa aparatu używa do przeniesienia się na pierwszy plan:
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) } // ... } } //... }
Najważniejsze informacje o kodzie
- Aplikacja zadeklarowała już w pliku manifestu, że potrzebuje uprawnienia
CAMERA. Aplikacja musi jednak też sprawdzić w czasie działania, czy użytkownik przyznał to uprawnienie. Jeśli aplikacja nie ma odpowiednich uprawnień, powinna poinformować o tym użytkownika. - Różne typy usług na pierwszym planie zostały wprowadzone w różnych wersjach platformy Android. Ten kod sprawdza, w jakiej wersji Androida jest uruchomiony, i prosi o odpowiednie uprawnienia.
- Kod sprawdza, czy nie wystąpił wyjątek
ForegroundServiceStartNotAllowedException, jeśli próbuje uruchomić usługę na pierwszym planie w niedozwolonej sytuacji (np. jeśli próbuje przenieść usługę na pierwszy plan, gdy aplikacja działa w tle).