In diesem Artikel diskutieren wir eine wichtige Komponente in der Android-Anwendungsentwicklung – den Android-Service. Anders als eine Activity läuft ein Service unter Android im Hintergrund. Ein Service hat keine UI und sein Lebenszyklus unterscheidet sich ebenfalls von dem einer Activity. Mithilfe eines Service können wir einige Hintergrundoperationen ausführen, z. B. das Laden einer Webseite von einem entfernten Server. Wir können einen Service verwenden, um Multitasking unter Android zu implementieren.

Android-Service-Überblick

Wir wissen, dass eine Android-Activity gestartet, gestoppt, zerstört oder sogar neu erstellt werden kann, wenn die Systemressourcen knapp werden. Ein Service hingegen ist auf einen längeren Lebenszyklus ausgelegt. Ein Service unter Android kann von einer Activity, einem Broadcast-Empfänger oder von anderen Services gestartet werden.

Es muss beachtet werden, dass die Verwendung eines Service nicht automatisch einen neuen Thread erstellt. Wenn wir daher eine einfache Logik in einem Service implementieren möchten, die keine lange Verarbeitung erfordert, müssen wir sie nicht in einem separaten Thread ausführen. Wenn wir jedoch komplexe Logik implementieren müssen, deren Verarbeitung lange dauert, müssen wir beim Erstellen neuer Threads vorsichtig sein; andernfalls kann es, da der Service im Hauptthread läuft, zu ANR-Problemen (Application Not Responding) kommen.

Die Hauptszenarien für die Verwendung eines Service in Android sind wie folgt:

  • Implementierung von Multitasking (Multi-Task)
  • Interprozesskommunikation (IPC)

Ein typisches Beispiel für den ersten Fall ist, wenn eine App Daten von einem Remote-Server herunterladen muss. In diesem Fall können Sie eine Activity verwenden, die mit dem Benutzer interagiert, und einen Service starten, während der Benutzer die App verwendet, damit er die Arbeit im Hintergrund abschließen kann. Es gibt auch ein Szenario, in dem der Service nach Abschluss seiner Aufgabe Informationen an den Benutzer sendet.

Im zweiten Fall möchten wir eine gemeinsame Funktionalität "teilen", damit verschiedene Anwendungen sie wiederverwenden können. Angenommen, wir haben einen Service, der E-Mails senden kann, und wir möchten diesen Service unter mehreren Anwendungen gemeinsam nutzen, sodass wir nicht denselben Code neu schreiben müssen. In diesem Fall können wir IPC verwenden, damit der Service eine "remote"-Schnittstelle bereitstellt, die von anderen Anwendungen aufgerufen werden kann.

Service-Grundlagen

Nachdem wir nun mehr über Services verstanden haben, erstellen wir einen. Um einen Service in Android zu erstellen, müssen wir von der Klasse Service erben.

public class TestService extends Service {

    @Override
    public IBinder onBind(Intent arg0) {        
        return null;
    }

}

Wie Sie sehen, haben wir nur eine Methode namens onBind implementiert. Im obigen Beispiel haben wir einen lokalen Service verwendet, daher gibt die Methode null zurück. Wie bereits erwähnt, hat ein Service einen eigenen Lebenszyklus, sodass wir einige Callback-Methoden überschreiben können, um seine verschiedenen Zustände zu behandeln:

public class TestService extends Service {

    @Override
    public void onCreate() {        
        super.onCreate();
    }

    @Override
    public void onDestroy() {        
        super.onDestroy();
    }

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

    @Override
    public IBinder onBind(Intent arg0) {        
        return null;
    }

}

Die erste Methode, onCreate, wird nur aufgerufen, wenn der Service erstellt wird. Wenn der Service bereits läuft, wird diese Methode nicht aufgerufen. Wir können sie nicht direkt aufrufen; sie wird vom System aufgerufen.

Die Methode onStartCommand ist die wichtigste Methode, denn sie wird aufgerufen, wenn wir den Service starten müssen. In dieser Methode wird der Intent übergeben, der beim Ausführen des Service gesendet wurde, sodass wir einige Informationen mit dem Service austauschen können. In dieser Methode implementieren wir unsere eigene Logik: Wenn es sich nicht um einen zeitintensiven Vorgang handelt, kann er direkt in dieser Methode ausgeführt werden; andernfalls kann ein Thread erstellt werden. Wie Sie sehen, muss diese Methode einen ganzzahligen Wert zurückgeben. Diese Ganzzahl legt fest, wie das System den Service behandeln soll:

  • START_STICKY: Mit diesem Rückgabewert wird unser Service, wenn das System ihn beendet, neu erstellt. Der Intent, der an den Service gesendet wurde, wird jedoch nicht erneut zugestellt. Auf diese Weise läuft der Service weiter.
  • START_NOT_STICKY: Wenn das System den Service beendet, wird er nicht neu erstellt, es sei denn, der Client ruft den onStart-Befehl explizit auf.
  • START_REDELIVER_INTENT: Funktioniert ähnlich wie START_STICKY. Zusätzlich wird in diesem Fall der Intent erneut an den Service zugestellt.

onDestroy ist eine Methode, die vom System aufgerufen wird, wenn der Service kurz vor der Zerstörung steht.

Sobald wir eine benutzerdefinierte Service-Klasse haben, müssen wir sie in Manifest.xml deklarieren, damit wir sie verwenden können.

<service android:name=".TestService"
         android:enabled="true"/>

Starten und Stoppen eines Service

Wie wir wissen, wird ein Service gestartet und irgendwann gestoppt, damit er seine Aufgabe erledigen kann. Angenommen, wir starten ihn aus einer Activity; wir können einen Intent verwenden, um einige Informationen an den Service zu übergeben. Angenommen, unsere Activity hat zwei Buttons, einen zum Starten und einen zum Stoppen des Service:

btnStart.setOnClickListener(new View.OnClickListener() {
 
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        i.putExtra("name", "SurvivingwithAndroid");        
        MainActivity.this.startService(i);        
    }
});
 
btnStop.setOnClickListener(new View.OnClickListener() {
 
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, TestService.class);
        MainActivity.this.stopService(i);
    }
});

In Zeile 5 des obigen Beispielcodes erstellen wir einen Intent, der den Klassennamen übergibt, um unseren Service zu behandeln, und wir legen einige Parameter wie name fest. Dann starten wir in Zeile 7 diesen Service. Auf dieselbe Weise stoppen wir in Zeile 17 diesen Service.

android-service-tutorial-1

Wenn Sie auf die Start-Schaltfläche klicken, erhalten Sie folgendes Log:

android-service-tutorial-2

Du kannst feststellen, dass die Methode onCreate aufgerufen wird. Denn dies ist das erste Mal, dass wir diesen Service starten. Wenn wir erneut auf die Start-Schaltfläche klicken, ruft das System onCreate nicht auf. Wenn wir auf die Stopp-Schaltfläche klicken, zerstört das System diesen Service.

IntentService

Wie bereits erwähnt, läuft ein Service im Hauptthread. Daher müssen wir sehr vorsichtig sein, wenn wir Logik in einem Service implementieren. Bedenke, dass diese Logik, wenn sie eine blockierende Operation ist oder lange zum Beenden braucht, ANR-Probleme verursachen kann. In solchen Fällen müssen wir die Logik in einen separaten Thread verschieben. Das bedeutet, einen Thread in der Methode onStartCommand zu erstellen und ihn dann auszuführen.

Eine weitere von Service abgeleitete Klasse, IntentService, kann unsere Entwicklung vereinfachen. Diese Klasse ist nützlich, wenn wir nicht mehrere Anfragen gleichzeitig verarbeiten müssen. Sie erstellt einen Worker-Thread, um verschiedene Anfragen zu verarbeiten. Die ausgeführten Operationen sind wie folgt:

  • Erstellt einen separaten Thread zur Verarbeitung von Anfragen.
  • Erstellt eine Anfragenwarteschlange und übergibt ihr gelegentlich einen Intent.
  • Erstellt eine Standardimplementierung von onStartCommand.
  • Beendet den Service, nachdem alle Anfragen ausgeführt wurden.

Wenn wir einen IntentService erstellen möchten, müssen wir von der Klasse IntentService statt von der Klasse Service erben:

public class TestIntentService extends IntentService {
 
    public TestIntentService() {
        super("TestIntentService");        
    }
 
    @Override
    protected void onHandleIntent(Intent intent) {
 
    }
 
}

In diesem Beispiel müssen wir nur die Methode onHandleIntent implementieren. Die hier implementierte externe Logik muss sich keine Gedanken darüber machen, ob die Operation zeitaufwendig ist, da diese Methode in einem separaten Thread aufgerufen wird.

Automatisches Starten eines Service

Oft möchten wir unseren Service automatisch starten, zum Beispiel automatisch beim Booten. Wir wissen, dass eine Komponente benötigt wird, um einen Service zu starten. Wie können wir das also automatisch tun? Wir können einen Broadcast-Empfänger verwenden, um den Service zu starten. Wenn wir ihn beispielsweise starten möchten, wenn das Smartphone hochfährt, können wir zuerst einen Broadcast-Empfänger erstellen, der auf dieses Ereignis (Boot) hört, und dann den Service starten.

public class BootBroadcast extends BroadcastReceiver {

    @Override
    public void onReceive(Context ctx, Intent intent) {        
        ctx.startService(new Intent(ctx, TestService.class));

    }

}

Deklariere es in Manifest.xml:

<receiver android:name=".BootBroadcast">    
    <intent-filter >
        <action android:name="android.intent.action.BOOT_COMPLETED"/>                
    </intent-filter>
</receiver>

Quelle: http://www.importnew.com/9019.html