Aby uruchomić usługę na pierwszym planie z aplikacji, musisz wykonać 2 czynności. Najpierw uruchom usługę, wywołując ją za pomocą funkcji context.startForegroundService()
. Następnie usługa wywołuje funkcję ServiceCompat.startForeground()
, aby stała się usługą 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 uruchamiania przez nią 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 o wyjątkach od tej zasady znajdziesz w artykule Ograniczenia uruchamiania usługi na pierwszym planie z tła.
Aplikacje kierowane na Androida 14 (API na poziomie 34) lub nowszego muszą prosić o odpowiednie uprawnienia dla typu usługi na pierwszym planie. Gdy aplikacja próbuje przenieść usługę na pierwszy plan, system sprawdza, czy ma odpowiednie uprawnienia, i jeśli nie ma, to zgłasza błąd
SecurityException
. Jeśli na przykład spróbujesz uruchomić usługę na pierwszym planie typulocation
, system sprawdzi, czy Twoja aplikacja ma już uprawnieniaACCESS_COARSE_LOCATION
lubACCESS_FINE_LOCATION
. Dokumentacja typu usługi na pierwszym planie zawiera listę wymagań 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
- Fragment kodu uruchamia usługę. Usługa nie jest jednak jeszcze uruchomiona na pierwszym planie. W ramach usługi musisz wywołać funkcję
ServiceCompat.startForeground()
, aby przenieść usługę na pierwszy plan.
Przenoszenie usługi na pierwszy plan
Gdy usługa jest uruchomiona, musisz wywołać funkcję ServiceCompat.startForeground()
, aby poprosić o jej uruchomienie na pierwszym planie. Zwykle wywołujesz tę metodę w metodzie onStartCommand()
usługi.
ServiceCompat.startForeground()
przyjmuje te parametry:
- Usługa.
- dodatnia liczba całkowita, która jednoznacznie identyfikuje powiadomienie usługi na pasku stanu;
- Obiekt
Notification
. - Typy usług na pierwszym planie, które określają zadania wykonywane przez usługę.
Typy usług na pierwszym planie, które przekazujesz do metody startForeground()
, zgodnie z typami zadeklarowanymi w pliku manifestu, w zależności od konkretnego zastosowania. Jeśli chcesz dodać więcej typów usług, ponownie zadzwoń 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
).
Poniższy przykład pokazuje kod, którego usługa aparatu używa do promowania się w usłudze na pierwszym planie:
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 w pliku manifestu zadeklarowała już, że potrzebuje uprawnienia
CAMERA
Aplikacja musi jednak też sprawdzić w czasie działania, czy użytkownik przyznał takie uprawnienia. Jeśli aplikacja nie ma odpowiednich uprawnień, powinna poinformować użytkownika o tym problemie. - Różne typy usług działających na pierwszym planie zostały wprowadzone w różnych wersjach platformy Android. Ten kod sprawdza, na jakiej wersji Androida działa, i prosi o odpowiednie uprawnienia.
- Kod sprawdza wartość
ForegroundServiceStartNotAllowedException
, aby sprawdzić, czy próbuje uruchomić usługę na pierwszym planie w sytuacji, gdy jest to niedozwolone (na przykład, gdy próbuje przenieść usługę na pierwszy plan podczas gdy aplikacja działa w tle).