Gestartete Dienste eignen sich hervorragend für Hintergrundvorgänge, aber was ist, wenn Sie einen interaktiveren Dienst benötigen?
. . . eine Art von Dienst, mit dem Ihre Aktivität interagieren kann.
Gebundene Dienste sind an andere Komponenten gebunden…
Ein gebundener Dienst ist an eine andere Anwendungskomponente gebunden, z. B. an eine Aktivität. Im Gegensatz zu einem gestarteten Dienst kann die Komponente mit dem gebundenen Dienst interagieren und ihre Methoden aufrufen.
OdometerService der öffentlichen Klasse erweitert den Service @Override öffentlicher IBinder onBind(Intent intent) } }
Der obige Code implementiert eine Methode, onBind(), die aufgerufen wird, wenn eine Komponente, z. B. eine Aktivität, den Dienst binden möchte. Es hat einen Parameter, eine Absicht, und gibt ein IBinder-Objekt zurück. IBinder ist eine Schnittstelle, die verwendet wird, um Ihre Servie an die Aktivität zu binden, und Sie müssen eine Implementierung davon in Ihrem Servicecode vorsehen.
Implementieren eines Binders
Sie implementieren den IBinder, indem Sie Ihrem Servicecode eine neue innere Klasse hinzufügen, die die Binder-Klasse erweitert (die die IBinder-Schnittstelle implementiert). Diese innere Klasse muss eine Methode enthalten, die Aktivitäten verwenden können, um einen Verweis auf den gebundenen Dienst abzuverweisen.
Wenn Sie einen gebundenen Dienst erstellen, müssen Sie eine Binder-Implementierung bereitstellen. öffentliche Klasse OdometerBinder erweitert Binder Die Aktivität verwendet diese Methode, um einen Verweis auf den OdometerService abzuverweisen. OdometerService getOdometer()" OdometerService.this zurückgeben; } }
Wir müssen eine Instanz des OdometerBinders in der onBind()-Methode von OdormeterService zurückgeben. Dazu erstellen wir ein neues privates Vaiable für den Inder, instanziieren es und geben es in der onBind()-Methode zurück.
Paket eu.kio.odometer; importieren android.app.Service; importieren android.content.Intent; importieren android.os.IBinder; importieren android.os.Binder; java.util.Random importieren; OdometerService der öffentlichen Klasse erweitert den Service Wir verwenden eine private Endvariable für unser IBinder-Objekt privates End-IBinderbinder = neuer OdometerBinder(); Dies ist unsere IBinder-Implementierung piblic Klasse OdometerBinder erweitert Binder OdometerService getOdometer()" OdometerService.this zurückgeben; } } @Override öffentlicher IBinder onBind(Intent intent) IBinder zurückgeben Rücksendebinder; } }
Hinzufügen einer getDistance()-Methode zum Dienst
Wir werden OdometerService eine Methode namens getDistnce() hinzufügen, die von unserer Aktivität aufgerufen wird. Wir erhalten es, um eine Zufallszahl zurückzugeben.
Hier ist der vollständige Code…
Paket eu.kio.odometer; importieren android.app.Service; importieren android.content.Intent; importieren android.os.IBinder; importieren android.os.Binder; java.util.Random importieren; OdometerService der öffentlichen Klasse erweitert den Service Wir verwenden ein privates Finale für unser IBinder-Objekt privates End-IBinderbinder = neuer OdometerBinder(); Wir verwenden Random()-Objekt, um Zufallszahlen zu generieren privates finaler Zufall = neuer Random(); Dies ist unsere IBinder-Implementierung öffentliche Klasse OdometerBinder erweitert Binder OdometerService getOdometer()" OdometerService.this zurückgeben; } } öffentlicher OdometerService() } @Override öffentlicher IBinder onBind(Intent intent) IBinder zurückgeben Rücksendebinder; } Hinzufügen der getDistance-Methode öffentliche summende double getDistance()" return random.nextDouble(); } }
Rufen Sie eine Aktivität ab, die an OdometerService gebunden werden soll, und rufen Sie die getDistance()-Methode auf.
eine TextView zeigt die Von der getDistance()-Methode von OdometerService zurückgegebene Nummer an
Was die Aktivität tun muss
Um eine Aktivität zum Herstellen einer Verbindung mit einem gebundenen Dienst und zum Aufrufen seiner Methoden zu erhalten, müssen Sie einige Schritte ausführen:
- Erstellen einer DienstverbindungD
ies verwendet das IBiner-Objekt des Dienstes, um eine Verbindung mit dem Dienst herzustellen. - Binden Sie die Aktivität an den Dienst
Sobald Sie sie an den Dienst gebunden haben, können Sie die Methoden des Dienstes direkt aufrufen - Interagieren mit dem DienstIn u
nserem Fall verwenden wir die getDistance()-Methode des Dienstes, um die Textansicht der Akteivity zu aktualisieren. - Entbindern vom Dienst, wenn Sie damit fertig sindWenn d
er Dienst nicht mehr verwendet wird, zerstört Android den Dienst, um Ressourcen freizugeben
Erstellen einer ServiceConnection
Eine ServiceConnection ist eine Schnittstelle, die es Ermöglicht, Ihre Aktivität an einen Dienst zu trennen. Es hat zwei Methoden, die Sie definieren müssen:
- onServiceConnected()
- onServiceDisconnected()
Die onServiceConnected()-Methode wird aufgerufen, wenn eine Verbindung mit der Sercie hergestellt wird.
Der onServiceDisconected() wird aufgerufen, wenn die Verbindung getrennt wird.
So sieht der Basiscode aus:
Paket eu.kio.odometer; importieren android.app.Activity; importieren android.content.Context; importieren android.content.Intent; importieren android.os.Bundle; importieren sie android.content.ServiceConnection; importieren android.os.Handler; importieren android.os.IBinder; importieren sie android.content.ComponentName; importieren android.widget.TextView; java.util.Locale importieren; Public Class MainActivity erweitert Die Aktivität privater OdometerService-Kilometerzähler; private boolesche gebunden = false; Erstellen eines Serviceverbindungsobjekts Private ServiceConnection-Verbindung = neue ServiceConnection()" @Override public void onServiceConnected(ComponentName componentName,IBinder binder) Code, der ausgeführt wird, wenn der Dienst verbunden ist } @Override public void onServiceDisconnected(ComponetName componentName) Code, der ausgeführt wird, wenn der Dienst getrennt wird } };
Die onServiceConnceted()-Methode wird aufgerufen, wenn eine Verbindung zwischen der Aktivität und dem Dienst hergestellt wird. Es braucht zwei Parameter:
- ComponentName
Dieses Objekt beschreibt den Dienst, der verbunden wurde - IBindert
his objet, der durch den Service definiert wird
Es gibt zwei Dinge, die wir die onServiceConnected()-Methode benötigen:
- Verwenden Sie es iBinder Parameter, um einen Verweis auf den Dienst, mit dem wir verbunde
n sindWir können dies tun, indem Sie den IBinder auf einen OdometerService.OdometerBinder (da dies der Typ von IBinder ist, den wir in OdometerService definiert) und rufen seine getOdometer() Methode. - Aufzeichnen, dass die Aktivität an den Dienst gebunden ist
Hier ist der Code, um diese Dinge zu tun:
..... Public Class MainActivity erweitert Die Aktivität privater OdometerService-Kilometerzähler; private boolesche gebunden = false; Erstellen eines Serviceverbindungsobjekts Private ServiceConnection-Verbindung = neue ServiceConnection()" @Override public void onServiceConnected(ComponentName componentName,IBinder binder) Gießmittel binder in OdometerService.OdometerBinder OdometerService.OdometerBinder KilometerzählerBinder = (OdometerService.OdometerBinder) Bindemittel; Verwenden Sie den IBinder, um einen Verweis auf den Dienst abzubekommen Kilometerzähler = KilometerzählerBinder.getOdometer(); Aufzeichnen, dass die Aktivität an den Dienst gebunden ist gebunden = wahr; } .....
Die onServiceDisconnected()-Methode wird aufgerufen, wenn der Dienst und die Aktivität getrennt werden. Es benötigt einen Parameter, ein ComponentName-Objekt, das den Dienst beschreibt.
Die einzige Sache, die wir brauchen, um die onServiceDisconnected() Methode zu tun, wenn es aufgerufen wird:
- Aufzeichnung, dass die Aktivität nicht mehr an den Dienst gebunden ist
Hier ist der Code, um das zu tun…
.... @Override public void onServiceDisconnected(ComponentName componentName) Code, der ausgeführt wird, wenn der Dienst getrennt wird Auf false gebunden, da MainACtivity nicht mehr an OdometerService gebunden ist bound = false; } ....
Binden und Entbinden vom Dienst
Verwenden von bindService() zum Binden des Dienstes
Wenn Sie Ihre Dienstaktivität an einen Dienst binden, tun Sie dies in der Regel an einem von zwei Orten:
- In der onStart()-Methode der Aktivi
tätWenn die Aktivität sichtbar wird - In der onCreate()-Methode der A
ktivitätWenn die Aktivität
Wir müssen nur Updates OdometerService anzeigen, wenn Mainactivity sichtbar ist, wo wir an den Dienst in seiner onStart() Methode binden.
Um eine Bindung an den Dienst zu erstellen, erstellen Sie zunächst eine explizite Absicht, die sich an den Dienst richtet, an den Sie binden möchten. Sie verwenden dann die bindSercice()-Methode der Aktivität, um den Dienst zu binden und ihn an die …
- die Absicht
- das vom Service definierte ServicConncetion-Objekt
- eine Flagge, um zu entzibe, wie Sie binden möchten
Hier ist der Code …
.... @Override geschützte void onStart()" super.onStart(); Absichtsabsicht = neue Absicht (dies, OdometerSerivice.class); bindService(intent, connection, Context.BIND_AUTO_CREATE); } ....
Im obigen Beispiel haben wir das Flag Context.BIND_AUTO_CRATE verwendet, um Anroid anzuweisen, den Dienst zu erstellen, wenn er noch nicht vorhanden ist. Es gibt andere Flags, die Sie stattdessen verwend
en können… Android-Doku
mentation:https://developer.android.com/reference/android/content/Context.html
Verwenden Sie unbindService(), um die Bindung vom Dienst zu entbinden.
Wenn Sie die Bindung ihrer Aktivität von einem Dienst aufbinden, fügen Sie den Code normalerweise der onStop()- oder onDestroy()-Methode Ihrer Aktivität hinzu. Es hängt davon ab, wo Sie Ihren bindService()-Code absetzen:
- Wenn Sie den Dienst in der onStart()-Methode Ihrer Aktivität an den Dienst gebunden haben, wird die Bindung in der onStop()-Methode von ihm ab.
- Wenn Sie den Dienst in der onCreate()-Methode Ihrer Aktivität an den Dienst gebunden haben, wird die Bindung in der onDestroy()-Methode von ihm ab.
Sie werden mithilfe der unbindService()-Methode von einem Dienst abgebunden. Die Methode übernimmt den Parameter ServiceConnection-Objekt.
Hier ist der Code…
.... private boolesche gebunden = false; .... @Override geschützte leere onStop()" super.onStop(); if(bound) unbindService(Verbindung); bound = false; } } ....
Im obigen Code verwenden wir den Wert der gebundenen Variablen, um zu testen, ob wir die Bindung vom Dienst aufbinden müssen.
Die letzte Sache ist, die Aktivität zu erhalten, um die getDistance()-Methode von OdometerService aufzurufen und ihren Wert anzuzeigen.
Wir rufen jede Sekunde die getDistance()-Methode des OdometerServic auf und aktualisieren die TextView mit ihrem Wert mithilfe eines Handlers.
Hier ist die Methode….
Private void displayDistance()" Abrufen der TextView endgültige TextView distanceView = (TextView)findViewById(R.id.distance); Erstellen eines neuen Handlers finalHandler handler = neuer Handler(); Rufen Sie die Post()-Methode des Handlers auf, indem Sie eine neue Runnable-Methode übergeben handler.post(neue Runnable()" @Override Öffentlicher void run()" Doppelabstand = 0,0; if(gebundener && Kilometerzähler != null)" Wenn wir einen Verweis auf den OdometerService haben und daran gebunden sind, rufen Sie getDistance() auf. Abstand = kilometerometer.getDistance(); } String distanceStr = String.format(Locale.getDefault(),"%1,,.2f Meilen",distance); distanceView.setText(distanceStr); /**Poste den Code in der Runnable an * nach einer Verzögerung von 1 Sekunde erneut ausgeführt werden. Da diese Codezeile in der Runnable- * run() method.it läuft jede Sekunde (mit einer leichten Verzögerung). */ handler.postDelayed(this,1000); } }); }
Vollständiger Code für kontext….
OdometerService:
Paket eu.kio.odometer; importieren android.app.Service; importieren android.content.Intent; importieren android.os.IBinder; importieren android.os.Binder; java.util.Random importieren; OdometerService der öffentlichen Klasse erweitert den Service Wir verwenden ein privates Finale für unser IBinder-Objekt privates End-IBinderbinder = neuer OdometerBinder(); privates finaler Zufall = neuer Random(); Dies ist unsere IBinder-Implementierung öffentliche Klasse OdometerBinder erweitert Binder OdometerService getOdometer()" OdometerService.this zurückgeben; } } öffentlicher OdometerService() } @Override öffentlicher IBinder onBind(Intent intent) TODO: Geben Sie den Kommunikationskanal an den Dienst zurück. neue UnsupportedOperationException("Noch nicht implementiert"); IBinder zurückgeben Rücksendebinder; } öffentliche summende double getDistance()" return random.nextDouble(); } }
Hauptaktivität:
Paket eu.kio.odometer; importieren android.app.Activity; importieren android.content.Context; importieren android.content.Intent; importieren android.os.Bundle; importieren sie android.content.ServiceConnection; importieren android.os.Handler; importieren android.os.IBinder; importieren sie android.content.ComponentName; importieren android.widget.TextView; java.util.Locale importieren; Public Class MainActivity erweitert Die Aktivität privater OdometerService-Kilometerzähler; private boolesche gebunden = false; Erstellen eines Serviceverbindungsobjekts Private ServiceConnection-Verbindung = neue ServiceConnection()" @Override public void onServiceConnected(ComponentName componentName,IBinder binder) Code, der ausgeführt wird, wenn der Dienst verbunden ist OdometerService.OdometerBinder KilometerzählerBinder = (OdometerService.OdometerBinder) Bindemittel; Verwenden Sie den IBinder, um einen Verweis auf den Dienst abzubekommen Kilometerzähler = KilometerzählerBinder.getOdometer(); Die Aktivität ist an den Dienst gebunden, so dass die gebundene Variable auf true gebunden = wahr; } @Override public void onServiceDisconnected(ComponentName componentName) Code, der ausgeführt wird, wenn der Dienst getrennt wird Auf false gebunden, da MainACtivity nicht mehr an OdometerService gebunden ist bound = false; } }; @Override geschützte void onStart()" super.onStart(); Absichtsabsicht = neue Absicht(this,OdometerService.class); bindService(intent,connection,Context.BIND_AUTO_CREATE); } @Override geschützte leere onStop()" super.onStop(); if(bound) Dadurch wird das SevicConnection-Objekt verwendet, um die Bindung vom Dienst zu trennen. unbindService(Verbindung); Wenn wir die Bindung aufbinden, setzen wir die Bindung an bound = false; } } Private void displayDistance()" Abrufen der TextView endgültige TextView distanceView = (TextView)findViewById(R.id.distance); Erstellen eines neuen Handlers finalHandler handler = neuer Handler(); Rufen Sie die Post()-Methode des Handlers auf, indem Sie eine neue Runnable-Methode übergeben handler.post(neue Runnable()" @Override Öffentlicher void run()" Doppelabstand = 0,0; if(gebundener && Kilometerzähler != null)" Wenn wir einen Verweis auf den OdometerService haben und daran gebunden sind, rufen Sie getDistance() auf. Abstand = kilometerometer.getDistance(); } String distanceStr = String.format(Locale.getDefault(),"%1,,.2f Meilen",distance); distanceView.setText(distanceStr); /**Poste den Code in der Runnable an * nach einer Verzögerung von 1 Sekunde erneut ausgeführt werden. Da diese Codezeile in der Runnable- * run() method.it läuft jede Sekunde (mit einer leichten Verzögerung). */ handler.postDelayed(this,1000); } }); } @Override geschützte void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Aktualisieren des TextView-Werts jede Sekunde displayDistance(); } }