Dienst im Vordergrund starten

Das Starten eines Vordergrunddienstes über Ihre App erfolgt in zwei Schritten. Zuerst müssen Sie den Dienst durch Aufrufen von context.startForegroundService() starten. Lassen Sie den Dienst dann ServiceCompat.startForeground() aufrufen, um ihn in einen Vordergrunddienst zu befördern.

Voraussetzungen

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

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

  • 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 anfordern. Wenn die App versucht, einen Dienst in den Vordergrund zu verschieben, prüft das System, ob die entsprechenden Berechtigungen vorhanden sind, 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 von Diensten im Vordergrund sind die erforderlichen Voraussetzungen für jeden Typ aufgeführt.

Dienst starten

Wenn Sie einen Dienst im Vordergrund starten möchten, müssen Sie ihn zuerst als normalen (nicht im Vordergrund ausgeführten) Dienst 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

  • Mit dem Code-Snippet wird ein Dienst gestartet. Der Dienst wird jedoch noch nicht im Vordergrund ausgeführt. Im Dienst selbst müssen Sie ServiceCompat.startForeground() aufrufen, um den Dienst zu einem Dienst im Vordergrund zu machen.

Dienst in den Vordergrund rücken

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

ServiceCompat.startForeground() verwendet die folgenden Parameter:

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

Angenommen, eine Fitness-App führt einen Lauf-Tracker-Dienst aus, der immer location-Informationen benötigt, aber möglicherweise keine Medien abspielen muss. Sie müssen sowohl location als auch mediaPlayback im Manifest deklarieren. Wenn ein Nutzer einen Lauf startet und nur seinen Standort erfassen möchte, sollte Ihre App startForeground() aufrufen und nur die Berechtigung ACCESS_FINE_LOCATION übergeben. Wenn der Nutzer dann Audio abspielen möchte, rufen Sie startForeground() noch einmal auf und übergeben Sie die bitweise Kombination aller Arten von Diensten im Vordergrund (in diesem Fall ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK).

Das folgende Beispiel zeigt den Code, den ein Kameradienst verwenden würde, um sich selbst zu einem Dienst im Vordergrund zu machen:

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

  • In der Manifestdatei der App wurde bereits deklariert, dass die Berechtigung CAMERA erforderlich ist. Die App muss jedoch auch zur Laufzeit prüfen, ob der Nutzer diese Berechtigung erteilt hat. Wenn die App nicht die richtigen Berechtigungen hat, sollte sie den Nutzer über das Problem informieren.
  • Mit verschiedenen Versionen der Android-Plattform wurden verschiedene Arten von Vordergrunddiensten eingeführt. Dieser Code prüft, welche Android-Version verwendet wird, und fordert die entsprechenden Berechtigungen an.
  • Der Code prüft auf ForegroundServiceStartNotAllowedException, falls versucht wird, einen Dienst im Vordergrund in einer Situation zu starten, die nicht zulässig ist (z. B. wenn versucht wird, den Dienst in den Vordergrund zu verschieben, während die App im Hintergrund ausgeführt wird).