Dienst im Vordergrund starten

Es gibt zwei Schritte, um einen Dienst im Vordergrund über Ihre App zu starten. Zuerst müssen Sie den Dienst mit context.startForegroundService() starten. Dann muss der Dienst ServiceCompat.startForeground() aufrufen, um sich selbst zu einem Dienst im Vordergrund zu machen.

Vorbereitung

Je nachdem, auf welches API-Level 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 keinen Dienst im Vordergrund starten, während die App im Hintergrund ausgeführt wird. Es gibt jedoch einige Ausnahmen. Weitere Informationen und Informationen zu den Ausnahmen von dieser Regel finden Sie unter Einschränkungen beim Starten eines Dienstes im Vordergrund aus dem 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 im Vordergrund vom Typ location zu starten, prüft das System, ob Ihre App bereits die Berechtigung ACCESS_COARSE_LOCATION oder ACCESS_FINE_LOCATION hat. In der Dokumentation zu den Typen von Diensten im Vordergrund sind die erforderlichen Voraussetzungen für jeden Typ von Dienst im Vordergrund 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 Informationen 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 zu einem Dienst im Vordergrund zu machen.

Dienst in den Vordergrund verschieben

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

ServiceCompat.startForeground() verwendet die folgenden Parameter:

Die Typen von Diensten im Vordergrund, die Sie an startForeground() übergeben, müssen je nach spezifischem Anwendungsfall im Manifest deklariert 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 sein Standort getrackt werden soll, 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 Typen von Diensten im Vordergrund (in diesem Fall ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK).

Im folgenden Beispiel wird der Code gezeigt, 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 Informationen zum Code

  • Die App hat im Manifest bereits deklariert, dass sie die Berechtigung CAMERA benötigt. Die App muss jedoch auch zur Laufzeit prüfen, ob der Nutzer diese Berechtigung gewährt hat. Wenn die App nicht die richtigen Berechtigungen hat, sollte sie den Nutzer über das Problem informieren.
  • Verschiedene Typen von Diensten im Vordergrund wurden mit verschiedenen Versionen der Android-Plattform eingeführt. Dieser Code prüft, welche Android-Version ausgeführt wird, und fordert die entsprechenden Berechtigungen an.
  • Der Code prüft auf ForegroundServiceStartNotAllowedException, falls versucht wird, einen Dienst im Vordergrund in einer nicht zulässigen Situation zu starten (z. B. wenn versucht wird, den Dienst in den Vordergrund zu verschieben, während die App im Hintergrund ausgeführt wird).