Uruchomienie usługi działającej na pierwszym planie z poziomu aplikacji wymaga wykonania 2 kroków. Najpierw musisz uruchomić usługę, wywołując metodę context.startForegroundService()
. Następnie usługa wywoła polecenie ServiceCompat.startForeground()
, aby przejść na pierwszy plan.
Wymagania wstępne
W zależności od poziomu interfejsu API, na który jest kierowana aplikacja, istnieją 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 działającej na pierwszym planie, gdy aplikacja działa w tle. Istnieje jednak kilka wyjątków. Więcej informacji i wyjątki od tej reguły znajdziesz w artykule Ograniczenia dotyczące uruchamiania usługi na pierwszym planie z poziomu tła.
Aplikacje kierowane na Androida 14 (API na poziomie 34) lub nowszego muszą prosić o odpowiednie uprawnienia dla danego typu usługi działającej na pierwszym planie. Gdy aplikacja próbuje przenieść usługę na pierwszy plan, system sprawdza odpowiednie uprawnienia i w przypadku ich braku zgłasza wyjątek
SecurityException
. Jeśli na przykład spróbujesz uruchomić usługę na pierwszym planie typulocation
, system sprawdzi, czy Twoja aplikacja ma już uprawnienieACCESS_COARSE_LOCATION
lubACCESS_FINE_LOCATION
. W dokumentacji typu usługi na pierwszym planie znajdziesz 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 samej usłudze musisz wywołać funkcję
ServiceCompat.startForeground()
, aby promować usługę na pierwszym planie.
Promowanie usługi na pierwszym planie
Gdy usługa jest uruchomiona, musisz wywołać 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.
- Liczba całkowita dodatnia, która w niepowtarzalny sposób identyfikuje powiadomienie usługi na pasku stanu.
- Sam obiekt
Notification
. - Typy usług na pierwszym planie określające pracę wykonywaną przez usługę.
Typy usług na pierwszym planie przekazywane do startForeground()
typów zadeklarowanych w pliku manifestu zależą od konkretnego zastosowania. Jeśli później będziesz potrzebować dodatkowych typów usług, możesz ponownie zadzwonić pod numer startForeground()
.
Załóżmy na przykład, że aplikacja do fitnessu uruchamia usługę śledzenia biegu, która zawsze potrzebuje informacji location
, ale może nie potrzebować odtwarzania multimediów. W pliku manifestu musisz zadeklarować zarówno location
, jak i mediaPlayback
. Jeśli użytkownik rozpocznie bieg i chce tylko śledzić swoją lokalizację, aplikacja powinna wywołać startForeground()
i przekazać tylko uprawnienie ACCESS_FINE_LOCATION
. Następnie, jeśli użytkownik chce rozpocząć odtwarzanie dźwięku, ponownie wywołaj funkcję startForeground()
i przekaż 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, aby promować się jako usługa 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 zadeklarowała już w pliku manifestu, że potrzebuje
CAMERA
uprawnienia. Aplikacja musi jednak również sprawdzać 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 działających na pierwszym planie zostały wprowadzone w różnych wersjach platformy Android. Ten kod sprawdza, w jakiej wersji Androida działa aplikacja, i prosi o odpowiednie uprawnienia.
- Kod sprawdza wartość
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).