AndroidMobile

Android Services

Im Gegensatz zu Activities, die eine grafische Schnittstelle präsentieren, laufen Services unsichtbar im Hintergrund. Sie können eine Suche im Internet starten, Daten verarbeiten, einen Content Provider aktualisieren, Android Notifications triggern oder Intents versenden.
Während Activities durch die Event-Handler ihres Lifecycles gestarted, gestoppt oder wiederhergestellt werden, sind Services dazu gedacht länger im Hintergrund zu laufen und Operationen auszuführen.

Du kannst Services von anderen Android Anwendungskomponenten aus starten, stoppen und kontrollieren. Dies behinaltet Activities, Broadcast Receiver und andere Services.

Wann immer deine Anwendung Funktionalität ohne direkte Benutzereingaben bereitstellt oder zeitaufwändige Operationen benötigt sind Services wahrscheinlich die Antwort.

Service erstellen

Um einen Service zu erstellen benötigst du eine Klasse die von Service erbt, dabei musst du die beiden Methoden onCreate() und onBind() überschreiben:

public class MyFirstService extends Service {
  @Override
  public void onCreate() {
    super.onCreate();
    // TODO:
  }

  @Override
  public IBinder onBind(Intent intent) {
    // TODO:
    return null;
  }
}

Nachdem wir unseren Service angelegt haben dürfen wir nicht vergessen ihn ins Android Manifest einzutragen, dabei steht der service tag innerhalb des application Knotens:

<service android:enabled=”true” android:name=”.MyFirstService”/>

Service ausführen ( onStartCommand )

Um eine Aufgabe von einem Service ausführen zu lassen überschreibst du den onStartCommand Event Handler deiner Serviceklasse.

Die onStartCommand Methode wird jedes Mal aufgerufen wenn der Service über startService gestartet wird, da ein Service meist öfter ausgeführt wird ist die Methode auch ein guter Ort um hier das Verhalten für ein neuerliches Aufrufen zu implementieren.

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
     startBackgroundTask(intent, startId);
     return Service.START_STICKY;
  }

Hinweis

Services laufen, auch wenn sie im Hintergrund ausgeführt werden, immer auf dem Main Thread. Das Standardvorgehen um den Main Thread nicht zu blockieren ist die Implementierung eines neuen Threads in onStartCommand für die eigentliche Aufgabe und den Service zu stoppen wenn die Aufgabe erledigt ist.

Service Konstanten – Rückgabewerte der onStartCommand Methode

  • START_STICKY: Beschreibt das Standardverhalten. Wenn der Service vom System beendet wird so wird er automatisch neu gestarted, dabei mußt du jedoch beachten das der übergebene Intent null ist.
  • START_NOT_STICKY: In diesem Modus wird der Service nicht vom System neu gestartet. Der Service wird ausdrüchklich über startService ausgeführt. Dies ist der Fall wenn ein Service z.B. in regelmäßigen Abständen Daten von einem Server aufruft, da macht es nichts wenn einmal ein Intervall ausgelassen wird.
  • START_REDELIVER_INTENT: Verhält sich ähnlich wie START_STICKY mit dem Unterschied das der ursprüngliche Intent-Parameter erhalten bleibt und der Prozess nur gestartet wird wenn er zuvor nicht vollständig abgearbeitet wurde.

Hinweis

Egal welche Service Konstante du verwendest du musst deinen Service immer mit stopService oder stopSelf beenden wenn er seine Aufgabe erledigt hat.

flag Paramater

Du kannst über den flag Parameter der onStartCommand Methode auslesen wie ein Service gestartet wurde, dabei kannst du im speziellen untersuchen ob folgende flags true sind:

  • START_FLAG_REDELIVERY: Wenn dieser Flag true ist wurde der Service vom System gestoppt bevor er explizit durch stopSelf korrekt beendet wurde. Dabei wird der Intent Parameter erneut geliefert.
  • START_FLAG_RETRY: In diesem Fall wurde der Service ebenfalls vom System angehalten jedoch mit dem Rückgabewert START_STICKY.

Service starten und beenden

Um einen Service zu starten musst du nur von der aufrufenden Komponente (Activtiy, Broadcast Receiver, anderer Service) die Methode startService ausführen wobei du entweder einen expliziten Intent abschicken kannst oder eine implizite Action.

private void startExplicitService() {
  // Explicitly start My First Service
  Intent intent = new Intent(this, MyFirstService.class);
  // TODO Add extras if required.
  startService(intent);
}
private void implicitStart() {
  // Implicitly start a music Service
  Intent intent = new Intent(MyMusicService.PLAY_ALBUM);
  intent.putExtra(MyMusicService.ALBUM_NAME_EXTRA, “After The Eulogy”);
  intent.putExtra(MyMusicService.ARTIST_NAME_EXTRA, “Boysetsfire”);
  startService(intent);
}

Benutze wieder einen Intent zum Stoppen des Service und übergib ihn der Methode stopService.

// stop a service explicitly.
stopService(new Intent(this, MyFirstService.class));
// Stop a service implicitly.
Intent intent = new Intent(MyMusicService.PLAY_ALBUM);
stopService(intent);

Service selbst beendet

Aufgrund seiner höheren Priorität wird ein Service nur in äußersten Notfällen vom System beendet. Deshalb solltest du, um ressourcenschonend und sauber zu entwickeln den Service explizit beenden wenn er seine Aufgabe erledigt hat.

Nach Aufruf der Methode stopSelf ermöglichst du dem System wieder Ressourcen frei zu geben, ansonsten würde der Service, falls er von außen nicht gestoppt wird, immer weiter laufen.

Service an Activities binden

Neben den bisher besprochenen gestarteten Services gibt es auch eine zweite Möglichkeit Services zu nutzen und zwar den gebundenen Service.

Dienste wie diese stellen eine detaillierte Schnittstelle zur Verfügung, über die Servicenutzer, eine Activity, mit ihnen kommunizieren können.

Ein gebundener Service läuft, im Gegensatz zu einem gestarteten Service, solange zumindest ein Client mit ihm verbunden ist.

Wie wissen bereits dass jede Klasse von Service die onBind() Methode überschreiben muss, jetzt werden wir diese so implementieren das sie einen gültigen Binder zurückliefert.

@Override
public IBinder onBind(Intent intent) {
  return binder;
}
public class LocalBinder extends Binder {
  LocalBinder getService() {
    return LocalBinder.this;
  }
}
private final IBinder binder = new LocalBinder();

Die Verbindung zwischen dem Service und einer Anwendungskomponente wird durch die ServiceConnection-Klasse erreicht. Um z.B.: eine Activity an einen Service zu binden musst du eine Instanz von ServiceConnection implementieren und die Methoden onServiceConnected und onServiceDisconnected überschreiben.

// Reference to the service
private MyFirstService mService;
// Handles the connection between the service and activity
private ServiceConnection mConnection = new ServiceConnection() {

  public void onServiceConnected(ComponentName className, IBinder service) {
    
    // Called when the connection is made.
    mService = ((MyFirstService.LocalBinder)service).getService();

  }

  public void onServiceDisconnected(ComponentName className) {
    
    // Received when the service unexpectedly disconnects.
    mService = null;

  }
};

Um das Bining auszuführen rufst du nur noch, am besten in der onStart Methode, bindService auf:

// Bind to the service
Intent bindIntent = new Intent(MyActivity.this, MyFirstService.class);
bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE);

Weiterführendes

Darüber hinaus gibt es noch den IntentService der dir das Threadhandling erleichtert und die Möglichkeit einen Vordergrundservice zu definieren um die Priorität im System nochmals zu erhöhen.

Literaturtip

Merken

vorheriger Beitrag

Coding Regeln

nächster Beitrag

UX Grundlagen - Utility

Der Schreiberling

Markus M.

Markus M.

In den letzten 15 Jahren als Consultant und Coach für namhafte internationale Kunden und Agenturen (z.B.: IGT, Red Bull, adidas, OMV, PEZ, Volksoper Wien, Jung von Matt, spreadshirt, Philotech, Wien IT, bet-at-home, Siemens, SAE Institut, draft fcb, seso, looom, bacardi, lindt, uvm.) hat sich eine Menge Wissen angesammelt welches ich hier in diesem Blog gerne mit euch teilen möchte.

Keine Meinung

schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.