Das Starten eines Dienstes im Vordergrund aus Ihrer App heraus erfolgt in zwei Schritten. Zuerst müssen Sie den Dienst durch Aufrufen von context.startForegroundService() starten. Lassen Sie dann den Dienst ServiceCompat.startForeground() aufrufen, um ihn 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 sich die App im Hintergrund befindet. 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. Wenn der App Berechtigungen fehlen, wird
SecurityExceptionausgegeben. Wenn Sie beispielsweise versuchen, einen Dienst im Vordergrund vom Typlocationzu starten, prüft das System, ob Ihre App bereits die BerechtigungACCESS_COARSE_LOCATIONoderACCESS_FINE_LOCATIONhat. 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 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
- 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 stellen
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 onStartCommand() des Dienstes auf.
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. - Der Typ oder die Typen des Dienstes im Vordergrund, die die vom Dienst ausgeführte Arbeit identifizieren
Die Typen von Diensten im Vordergrund, die Sie an startForeground() übergeben, müssen je nach Anwendungsfall Typen sein, die im Manifest deklariert sind. 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üssten 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 die Audiowiedergabe starten 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).
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 App wurde bereits im Manifest deklariert, dass die Berechtigung
CAMERAerforderlich ist. 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. - Mit verschiedenen Versionen der Android-Plattform wurden unterschiedliche Typen von Diensten im Vordergrund eingeführt. Dieser Code prüft, welche Android-Version verwendet wird, und fordert die entsprechenden Berechtigungen an.
- Der Code sucht nach
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 sich die App im Hintergrund befindet).