Alles zu Services unter Android

Android Entwicklung: Grundlagen Logo
Was ist ein Service?

In Android ist ein Service eine spezielle Komponente, die es ermöglicht, Aufgaben im Hintergrund auszuführen, ohne dass der Benutzer mit der Anwendung interagieren muss. Dies ist besonders nützlich für langandauernde Operationen wie das Abspielen von Musik, das Abrufen von Daten von einem Server oder das Nachverfolgen der GPS-Position eines Geräts. Ein Service läuft eigenständig und kann unabhängig vom Lebenszyklus anderer Komponenten wie Activities operieren. Dies bedeutet, dass er weiterhin aktiv bleibt, auch wenn der Benutzer die App wechselt oder die ursprüngliche Komponente, die den Service gestartet hat, beendet wird.

Ein Service wird in der Regel durch eine andere App-Komponente wie eine Activity oder ein Content Provider gestartet und muss in der Datei AndroidManifest.xml registriert werden. Es gibt zwei grundlegende Arten von Services: Unbound Services und Bound Services. Ein Unbound Service wird durch den Aufruf von startService() gestartet und führt eine bestimmte Aufgabe aus, bis er manuell oder automatisch beendet wird. Der Bound Service hingegen erlaubt anderen App-Komponenten, sich an ihn zu binden und über eine Schnittstelle direkt mit ihm zu kommunizieren. Diese Art von Service wird typischerweise verwendet, wenn eine engere Zusammenarbeit zwischen dem Service und den anderen Komponenten erforderlich ist, zum Beispiel für die Übertragung von Echtzeitdaten.

Der Lebenszyklus eines Services ist von Android durch mehrere Callback-Methoden wie onCreate(), onStartCommand(), onBind(), und onDestroy() definiert. Diese Methoden steuern den Übergang des Services durch verschiedene Zustände, von der Initialisierung bis zur endgültigen Beendigung. Dies hilft Entwicklern, Ressourcen effizient zu verwalten und den Service sicher und stabil zu halten.

Services sind eine wichtige Komponente in Android-Anwendungen, da sie die Möglichkeit bieten, Hintergrundprozesse ohne Benutzerinteraktion auszuführen. Sie tragen zur Verbesserung der Benutzererfahrung bei, indem sie kontinuierliche Operationen ermöglichen, ohne die App im Vordergrund halten zu müssen.

 

Welche Service-Arten gibt es?

Grundsätzlich gibt es zwei Arten von Services:

Started/Unbound Service

Ein Unbound-Service ist ein Service, den eine andere App-Komponente (z.B. Activity) durch den Aufruf von "startService()" startet, was wiederum zu einem Aufruf der Methode "onStartCommand()" des Services führt. Ein solcher Service hat einen eigenen Lebenszyklus, der völlig unabhängig vom Lebenszyklus derjenigen Komponente ist, die diesen gestartet hat. Der Unbound-Service kann auf zwei unterschiedliche Weisen beendet werden: Entweder beendet der Service sich nach Erledigung seiner Aufgabe durch den Aufruf der Methode "stopSelf()" selbst oder er wird durch eine andere Komponente mittels der "stopService()"-Methode beendet.

 

Bound Service

Ein Bound-Service ist ein Service, der es App-Komponenten (z.B. Activity, Content Provider) erlaubt, diesen an sich zu binden, indem die "bindService()"-Methode aufgerufen wird. Dabei sind sowohl Komponenten der eigenen App, als auch Komponenten anderer Apps gemeint. Ein solcher Service muss am Ende über die Methode "onUnbind()" explizit wieder gelöst werden. Dabei besteht die Möglichkeit, dass sich mehrere Komponenten im selben Prozess gleichzeitig mit einem Bound-Service verbinden können.

 

Welchen Lebenszyklus haben Services?
Ein Service verfügt, genau wie eine Activity, über einen eigenen Lebenszyklus mit verschiedenen Callback-Methoden. Wenn du möchtest, kannst du diese Methoden implementieren, um Zustands-Änderungen eines Service zu überwachen. Nachfolgend zeigen wir dir zwei Schaubilder für den Lebenszyklus eines "Unbound-" und "Bound-Services". Jeweils direkt unterhalb eines Schaubildes beschreiben wir kurz die unterschiedlichen Methoden (haben Buchstaben) und Zustände (haben Nummern).

 

Lebenszyklus für einen Unbound Service:

Lebenszyklus: Unbound Service

 

a) Methode: onCreate()
Android ruft diese Callback-Methode auf, wenn der Service erstmalig erstellt wird. Die Methode führt dabei initiale und einmalige Setup-Prozeduren durch. Sofern der Service bereits läuft, wird diese Methode natürlich nicht aufgerufen. Die Methode darf zudem nicht direkt aufgerufen werden, sondern nur über die "startService()"-Methode.

Service: onCreate()-Methode

 

(1) Zustand: Created
Nachdem die Methode "onCreate()" aufgerufen wurde, ist der Service im Zustand "Created".

 

b) Methode: onStartCommand()
Das System ruft diese Methode immer dann auf, wenn eine andere Komponente, wie z.B. eine Activity, durch den Aufruf von "startService()" das Starten des Services anfordert. Falls du die "onStartCommand()"-Methode implementierst, musst du den Service durch die Methode "stopService()" auch wieder stoppen, sobald dieser seine Arbeit beendet hat. Auch hier gilt wieder, die Methode nicht direkt, sondern über "startService()" aufzurufen!

Service: onStartCommand()-Methode
Der Methode werden drei Parameter übergeben:

intent: Der Intent, der von der anfordernden Komponente über "startService()" mitgegeben wurde.

flags: Flags sind zusätzliche Informationen, die zur Startaufforderung mitgegeben werden. Sie sind wichtig, falls der Prozess, indem sich der Service befindet, plötzlich durch Speichernot beendet wird. Wenn dieser Fall eintritt, muss Android nämlich wissen, was dann passieren soll. Dabei kann Android über die folgenden Flags mitgeteilt werden, was es tun soll:

a) START_REDELIVER_INTENT: Hier startet Android den Prozess neu, sobald wieder genug Speicher da ist und es erfolgt ein Aufruf der "onStartCommand()"-Methode mit dem letzten Intent-Objekt als Parameter.

b) START_STICKY: Hier startet Android ebenfalls den Prozess neu, sobald wieder genug Speicher da ist und es erfolgt ein Aufruf der "onStartCommand()"-Methode mit Null als Parameter für den Intent.

c) START_NOT_STICKY: Hier startet Android den Prozess nicht neu.

startId: Dieser Parameter dient zur eindeutigen Identifizierung des Services. Sofern ein Service etwa über die Methode "stopSelfResult()" zerstört werden soll, wird diese ID benötigt.

 

(2) Zustand: Running
Nach den Aufrufen von "startService()" und "onStartCommand()" befindet sich ein Service im Zustand "Running" und verarbeitet eine Operation, wie z.B. das Abspielen von Musik im Hintergrund.

 

c) Methode: stopSelf() oder stopService()
Für das Beenden eines Services gibt es zwei unterschiedliche Methoden, die folgendermaßen unterschieden werden:

-> stopSelf():  Diese Methode verwendet ein Service, um sich nach der Durchführung einer Operation selbst zu beenden.

-> stopService(): Diese Methode wird von einer anderen Komponente, wie z.B. einer Activity verwendet, um einen Service zu beenden.

Service: stopService()-Methode

 

(3) Zustand: Stopped
Nachdem der Service durch eine der beiden Methoden "stopSelf()" oder "stopService()" beendet wurde, befindet sich der Service im Zustand "Stopped".

 

d) Methode: onDestroy()
Android ruft diese Methode auf, um dem Service mitzuteilen, dass dieser überflüssig geworden ist und nun zerstört wird. Der Service sorgt dann in einem solchen Fall dafür, dass alle Ressourcen (z.B. Threads) wieder freigegeben werden.

Service: onDestroy()-Methode

 

(4) Zustand: Shut down
Nachdem die Methode "onDestroy()" aufgerufen wurde, ist der Service nicht länger am Leben und alle von ihm belegten Ressourcen sind wieder freigegeben.

 

Lebenszyklus für einen Bound Service:

Lebenszyklus: Bound Service

 

Info: Die Methoden "onCreate()" und "onDestroy()" sowie die Zustände "Created" und "Shut Down" sind zwischen "Unbound Services" und "Bound Services" exakt gleich und aus diesem Grund verzichten wir hier auf eine erneute Beschreibung. Falls du etwas zu diesen Methoden bzw. Zuständen wissen möchtest, musst du einfach nur ein Stückchen hochscrollen. Wir starten diesmal die Erklärungen bei der Methode "onBind()" und beenden diese mit dem Zustand "Unbounded".

 

b) Methode: onBind()
Android ruft diese Methode auf, wenn eine andere Komponente sich mit dem Service durch den Aufruf von "bindService()" verbinden will. Wenn du die Methode "onBind()" implementierst, musst du eine Schnittstelle zur Verfügung stellen, so dass die Komponenten mit dem Service kommunizieren können. Das geschieht durch die Rückgabe eines "IBinder"-Objekts. Falls du keine Verbindung herstellen möchtest, dann gibst du schlicht "Null" zurück.

Service: onBind()-Methode

 

(2) Zustand: Bounded
Sobald die Methode "onBind()" aufgerufen wurde, befindet sich ein Service im Zustand "Bounded", d.h. dass eine Komponente nun an diesen Service gebunden ist.

 

c) Methode: onUnbind()
Diese Methode wird von Android aufgerufen, wenn sich Komponenten (z.B. Activities) von einer bestimmten, vom Service veröffentlichten Schnittstelle getrennt haben. Dabei lösen sich die Komponenten konkret über die Methode "unbindService()" vom Service. Der Übergabeparameter der "onUnbind()"-Methode ist der "Intent", der verwendet wurde, um sich an diesen Service zu binden. Der Rückgabewert der Methode "onUnbind()" ist ein Boolean-Wert. Sofern hier "true" zurückgegeben wird, bedeutet das, dass die "onRebind()"-Methode des Services später aufgerufen wird, d.h. sobald sich neue Komponenten mit dem Service verbinden möchten. Bei der Standardimplementierung passiert dagegen nichts und es wird "false" zurückgegeben.

Service: onUnbind()-Methode

 

(3) Zustand: Unbounded
Sobald sich alle Komponenten über die Methode "onUnbind()" von einem Service gelöst haben, befindet sich dieser im Zustand "Unbounded".