Dienst im Vordergrund starten

Es sind zwei Schritte erforderlich, um einen Dienst im Vordergrund über Ihre App zu starten. Zuerst müssen Sie den Dienst starten, indem Sie context.startForegroundService() aufrufen. Rufen Sie dann ServiceCompat.startForeground() auf, um den Dienst in einen Dienst im Vordergrund zu versetzen.

Voraussetzungen

Je nachdem, auf welche API-Ebene Ihre App ausgerichtet ist, gibt es einige Einschränkungen, wann eine App einen Dienst im Vordergrund starten kann.

  • Apps, die auf Android 12 (API-Level 31) oder höher ausgerichtet sind, dürfen mit wenigen Ausnahmen keinen Dienst im Vordergrund starten, während die App im Hintergrund ausgeführt wird. Weitere Informationen und Informationen zu den Ausnahmen von dieser Regel finden Sie unter Einschränkungen beim Starten eines Dienstes im Vordergrund aus dem Hintergrund.

  • Für Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind, müssen die entsprechenden Berechtigungen für den Typ des Dienstes im Vordergrund angefordert werden. Wenn die App versucht, einen Dienst in den Vordergrund zu stellen, prüft das System die entsprechenden Berechtigungen und löst SecurityException aus, wenn der App Berechtigungen fehlen. Wenn Sie beispielsweise versuchen, einen Dienst vom Typ location im Vordergrund zu starten, prüft das System, ob Ihre App bereits die Berechtigung ACCESS_COARSE_LOCATION oder ACCESS_FINE_LOCATION hat. In der Dokumentation zu Typen der Dienste im Vordergrund sind die erforderlichen Voraussetzungen für jeden Typ aufgeführt.

Dienst starten

Um einen Dienst im Vordergrund zu starten, müssen Sie ihn zuerst als normalen Dienst (nicht im Vordergrund) starten:

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);

Wichtige Punkte zum Code

  • Das Code-Snippet startet einen Dienst. Der Dienst wird jedoch noch nicht im Vordergrund ausgeführt. Im Dienst selbst müssen Sie ServiceCompat.startForeground() aufrufen, um den Dienst in einen Dienst im Vordergrund zu verschieben.

Dienste in den Vordergrund stellen

Sobald ein Dienst ausgeführt wird, müssen Sie ServiceCompat.startForeground() aufrufen, um zu verlangen, dass der Dienst im Vordergrund ausgeführt wird. Normalerweise wird diese Methode in der Methode onStartCommand() des Dienstes aufgerufen.

ServiceCompat.startForeground() verwendet die folgenden Parameter:

  • Der Dienst.
  • Eine positive Ganzzahl, die die Benachrichtigung des Dienstes in der Statusleiste eindeutig identifiziert.
  • Das Notification-Objekt selbst.
  • Die Typen des Dienstes im Vordergrund, die die vom Dienst ausgeführte Arbeit angeben

Die Typen von Diensten im Vordergrund, die Sie je nach Anwendungsfall an startForeground() im Manifest deklarierte Typen übergeben. Wenn Sie weitere Dienstleistungstypen hinzufügen möchten, können Sie startForeground() noch einmal aufrufen.

Angenommen, eine Fitness-App verwendet einen Lauf-Tracker-Dienst, für den immer location-Informationen erforderlich sind, aber möglicherweise keine Medien abgespielt werden müssen. Sie müssen sowohl location als auch mediaPlayback im Manifest deklarieren. Wenn ein Nutzer einen Lauf startet und nur seinen Standort erfassen lassen möchte, sollte Ihre App startForeground() aufrufen und nur die Berechtigung ACCESS_FINE_LOCATION übergeben. Wenn der Nutzer dann die Audiowiedergabe starten möchte, rufen Sie startForeground() noch einmal auf und übergeben Sie die binäre Kombination aller Typen von Diensten im Vordergrund (in diesem Fall ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK).

Das folgende Beispiel zeigt den Code, mit dem sich ein Kameradienst zu einem Dienst im Vordergrund befördern würde:

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)
            }
            // ...
        }
    }

    //...
}

Wichtige Punkte zum Code

  • Die App hat bereits im Manifest erklärt, dass sie die Berechtigung CAMERA benötigt. Die App muss jedoch auch zur Laufzeit prüfen, ob der Nutzer diese Berechtigung erteilt hat. Wenn die App nicht über die erforderlichen Berechtigungen verfügt, sollte der Nutzer darüber informiert werden.
  • Mit verschiedenen Versionen der Android-Plattform wurden unterschiedliche Typen von Diensten im Vordergrund eingeführt. Mit diesem Code wird geprüft, welche Android-Version verwendet wird, und die entsprechenden Berechtigungen werden angefordert.
  • Der Code prüft, ob ForegroundServiceStartNotAllowedException vorhanden ist, falls versucht wird, einen Dienst im Vordergrund zu starten, wenn dies nicht zulässig ist. Das ist beispielsweise der Fall, wenn versucht wird, den Dienst in den Vordergrund zu verschieben, während die App im Hintergrund ausgeführt wird.