Ein gebundener Dienst ist der Server in einer Client-Server-Schnittstelle. Damit können Komponenten z. B. Aktivitäten, die an den Dienst gebunden sind, Anfragen senden, Antworten empfangen und Interprocess Communication (IPC) Ein gebundener Dienst ist in der Regel nur verfügbar, während er einen anderen Dienst bedient. Anwendungskomponente und wird nicht unbegrenzt im Hintergrund ausgeführt.
In diesem Dokument wird beschrieben, wie Sie einen gebundenen Dienst erstellen und binden. von anderen Anwendungskomponenten zum Dienst. Weitere Informationen zu Diensten in allgemeine Informationen, z. B. wie Benachrichtigungen von einem Dienst zugestellt und der Dienst ausgeführt wird im Vordergrund finden Sie im Übersicht über die Dienste
Grundlagen
Ein gebundener Dienst ist eine Implementierung der Klasse Service
, mit der sich
andere Anwendungen sich an sie binden und mit ihr interagieren. Um eine Bindung für eine
implementieren Sie die Callback-Methode onBind()
. Dieses
gibt ein IBinder
-Objekt zurück, das die Programmierschnittstelle definiert, die
über die Clients mit dem Dienst interagieren können.
An gestarteten Dienst binden
Wie in der Übersicht über die Dienste beschrieben,
können Sie einen Dienst erstellen,
der sowohl gestartet als auch gebunden ist. Das heißt, Sie können
indem Sie startService()
aufrufen. Dadurch kann der
auf unbestimmte Zeit. Sie können auch zulassen, dass ein Client
an den Dienst gebunden wird, indem Sie
bindService()
wird angerufen.
Wenn Sie Ihren Dienst starten und gebunden haben,
Das System zerstört den Dienst nicht, wenn alle Clients die Bindung aufheben.
Stattdessen müssen Sie
beenden Sie den Dienst explizit durch Aufrufen von stopSelf()
oder stopService()
.
Normalerweise implementieren Sie entweder onBind()
oder onStartCommand()
ist es manchmal
notwendig, um
um beide zu implementieren. Beispielsweise kann ein Musikplayer seinen Dienst
und bindend. So kann der Dienst durch eine Aktivität gestartet werden,
und die Musik wird weiter abgespielt, auch wenn der Nutzer die App verlässt. Wenn die Nutzenden
an die Anwendung zurückgegeben wird, kann die Aktivität an den Dienst gebunden werden, um die Kontrolle über
Wiedergabe starten.
Weitere Informationen zum Dienstlebenszyklus beim Hinzufügen einer Bindung zu einem gestarteten Dienst Weitere Informationen finden Sie im Abschnitt Lebenszyklus eines gebundenen Dienstes verwalten.
Ein Client bindet sich an einen Dienst, indem er Folgendes aufruft:
bindService()
Wenn dies der Fall ist,
eine Implementierung von ServiceConnection
bereitstellen, die
überwacht die Verbindung mit dem Dienst. Der Rückgabewert von
bindService()
gibt an, ob der
der angeforderte Dienst existiert und ob der Client Zugriff darauf hat.
Wann?
stellt das Android-System die Verbindung
zwischen Client und Dienst her.
ruft onServiceConnected()
an
am ServiceConnection
. Die
Die Methode onServiceConnected()
enthält ein IBinder
.
, das der Client dann für die Kommunikation mit dem gebundenen Dienst verwendet.
Sie können mehrere Clients gleichzeitig mit einem Dienst verbinden. Die
Das System speichert den Kommunikationskanal des IBinder
-Dienstes im Cache.
Mit anderen Worten, das System ruft die onBind()
des Dienstes auf
, um die IBinder
nur zu generieren, wenn die erste
Clientbindungen. Das System liefert dieselben IBinder
alle zusätzlichen Clients, die an denselben Dienst gebunden sind, ohne
Noch einmal onBind()
.
Wenn der letzte Client die Bindung an den Dienst aufhebt, wird der Dienst vom System gelöscht, es sei denn, der
Dienst wurde mit startService()
gestartet.
Der wichtigste Teil der Implementierung eines gebundenen Dienstes ist das Definieren der Schnittstelle
das die Callback-Methode onBind()
zurückgibt. Die folgenden
werden verschiedene Möglichkeiten erläutert,
IBinder
-Schnittstelle.
gebundenen Dienst erstellen
Wenn Sie einen Dienst erstellen, der eine Bindung bereitstellt, müssen Sie einen IBinder
angeben
, die die Programmierschnittstelle zur Verfügung stellt, über die Clients mit dem Dienst interagieren können. Es
können Sie die Schnittstelle auf drei Arten definieren:
- Binder-Klasse erweitern
- Wenn Ihr Dienst privat ist und im selben Prozess ausgeführt wird
als Client, was häufig verwendet wird, erstellen Sie Ihre Schnittstelle, indem Sie den
Binder
Klasse und eine Instanz davononBind()
Der Client empfängt dieBinder
und kann damit direkt auf öffentliche Methoden zugreifen, die entweder imBinder
verfügbar sind oder derService
.Dies ist die bevorzugte Methode, wenn Ihr Dienst nur ein Hintergrund-Worker ist . Der einzige Anwendungsfall, wenn dies nicht die bevorzugte Methode zum Erstellen Ihrer Schnittstelle ist, ist wenn Ihr Dienst von anderen Anwendungen oder in separaten Prozessen verwendet wird.
- Messenger verwenden
- Wenn Sie Ihre Oberfläche für verschiedene Prozesse benötigen,
Schnittstelle für den Dienst mit einem
Messenger
. Auf diese Weise kann der Dienst definiert einHandler
, das auf verschiedene Typen vonMessage
-Objekten reagiert.Dieses
Handler
ist die Grundlage für einMessenger
, das dann einIBinder
teilen kann mit dem Client, damit dieser mithilfe vonMessage
-Objekten Befehle an den Dienst senden kann. Außerdem kann der Client eineMessenger
von damit der Dienst Nachrichten zurücksenden kann.Dies ist die einfachste Methode, um eine Interprozesskommunikation (IPC) durchzuführen, da der
Messenger
alle Anfragen in einem einzigen Thread in die Warteschlange stellt. Thread-sicher zu machen. - AIDL verwenden
- Android Interface Definition Language (AIDL) zerlegt Objekte in
Primitiven, die das Betriebssystem verstehen kann, und verteilt sie zwischen Prozessen,
IPC Das vorherige Verfahren, bei dem ein
Messenger
verwendet wird, basiert tatsächlich auf AIDL als zugrunde liegen.Wie im vorherigen Abschnitt erwähnt, erstellt
Messenger
eine Warteschlange mit alle Clientanfragen in einem Thread enthalten, damit der Dienst eine Anfrage nach der anderen empfängt. Wenn: Wenn Ihr Dienst jedoch mehrere Anfragen gleichzeitig verarbeiten soll, können Sie AIDL verwenden. . In diesem Fall muss Ihr Dienst threadsicher und Multithreading-fähig sein.Um AIDL direkt zu verwenden, eine
.aidl
-Datei erstellen, die die Programmierschnittstelle definiert. Die Android SDK-Tools nutzen diese Datei aus, um eine abstrakte Klasse zu generieren, die das -Interface implementiert und IPC verarbeitet. die innerhalb Ihres Dienstes erweitert werden können.
Hinweis:Für die meisten Anwendungen ist AIDL nicht die beste Wahl für einen gebundenen Dienst erstellen, da dies Multithreading-Funktionen und kann die Implementierung komplizierter gestalten. Daher wird in diesem Dokument nicht erläutert, wie um sie für Ihren Dienst zu nutzen. Wenn Sie sicher sind, dass Sie Wenn Sie AIDL direkt verwenden möchten, siehe AIDL Dokument.
Binder-Klasse erweitern
Wenn nur die lokale Anwendung Ihren Dienst verwendet und diese nicht
prozessübergreifend arbeiten,
Dann können Sie Ihre eigene Binder
-Klasse implementieren, die Ihrem Client direkte Zugriffe bereitstellt.
auf öffentliche Methoden
im Dienst zugreifen können.
Hinweis:Dies funktioniert nur, wenn sich Client und Dienst im selben Anwendung und Prozess, was am häufigsten ist. Das eignet sich gut für eine Musik, -Anwendung, die eine Aktivität mit ihrem eigenen Dienst verknüpfen muss, der Musik im Hintergrund.
Und so funktioniert es:
- Erstellen Sie in Ihrem Dienst eine Instanz von
Binder
, die eines der folgenden: <ph type="x-smartling-placeholder">- </ph>
- Enthält öffentliche Methoden, die der Client aufrufen kann.
- Gibt die aktuelle
Service
-Instanz zurück, die die öffentlichen Methoden der aufrufen kann. - Gibt eine Instanz einer anderen Klasse zurück, die vom Dienst mit öffentlichen Methoden gehostet wird aufrufen kann.
- Gibt diese Instanz von
Binder
von der Callback-MethodeonBind()
zurück. - Empfangen Sie im Client die
Binder
von der Callback-MethodeonServiceConnected()
und den gebundenen Dienst mit den bereitgestellten Methoden aufrufen.
Hinweis:Dienst und Client müssen sich im selben , damit der Client das zurückgegebene Objekt umwandeln und seine APIs ordnungsgemäß aufrufen kann. Dienst und der Kunde müssen sich im selben Prozess befinden. Marshalling zwischen Prozessen.
Hier sehen Sie als Beispiel einen Dienst, der Clients Zugriff auf Methoden im Dienst über
eine Binder
-Implementierung:
Kotlin
class LocalService : Service() { // Binder given to clients. private val binder = LocalBinder() // Random number generator. private val mGenerator = Random() /** Method for clients. */ val randomNumber: Int get() = mGenerator.nextInt(100) /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ inner class LocalBinder : Binder() { // Return this instance of LocalService so clients can call public methods. fun getService(): LocalService = this@LocalService } override fun onBind(intent: Intent): IBinder { return binder } }
Java
public class LocalService extends Service { // Binder given to clients. private final IBinder binder = new LocalBinder(); // Random number generator. private final Random mGenerator = new Random(); /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { LocalService getService() { // Return this instance of LocalService so clients can call public methods. return LocalService.this; } } @Override public IBinder onBind(Intent intent) { return binder; } /** Method for clients. */ public int getRandomNumber() { return mGenerator.nextInt(100); } }
LocalBinder
stellt die getService()
-Methode für Clients zum Abrufen von
aktuelle Instanz von LocalService
. Dadurch können Clients öffentliche Methoden in der
. Clients können beispielsweise getRandomNumber()
über den Dienst aufrufen.
Hier ist eine Aktivität, die eine Bindung an LocalService
herstellt und getRandomNumber()
aufruft
wenn auf eine Schaltfläche geklickt wird:
Kotlin
class BindingActivity : Activity() { private lateinit var mService: LocalService private var mBound: Boolean = false /** Defines callbacks for service binding, passed to bindService(). */ private val connection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { // We've bound to LocalService, cast the IBinder and get LocalService instance. val binder = service as LocalService.LocalBinder mService = binder.getService() mBound = true } override fun onServiceDisconnected(arg0: ComponentName) { mBound = false } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) } override fun onStart() { super.onStart() // Bind to LocalService. Intent(this, LocalService::class.java).also { intent -> bindService(intent, connection, Context.BIND_AUTO_CREATE) } } override fun onStop() { super.onStop() unbindService(connection) mBound = false } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute). */ fun onButtonClick(v: View) { if (mBound) { // Call a method from the LocalService. // However, if this call is something that might hang, then put this request // in a separate thread to avoid slowing down the activity performance. val num: Int = mService.randomNumber Toast.makeText(this, "number: $num", Toast.LENGTH_SHORT).show() } } }
Java
public class BindingActivity extends Activity { LocalService mService; boolean mBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to LocalService. Intent intent = new Intent(this, LocalService.class); bindService(intent, connection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); unbindService(connection); mBound = false; } /** Called when a button is clicked (the button in the layout file attaches to * this method with the android:onClick attribute). */ public void onButtonClick(View v) { if (mBound) { // Call a method from the LocalService. // However, if this call is something that might hang, then put this request // in a separate thread to avoid slowing down the activity performance. int num = mService.getRandomNumber(); Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); } } /** Defines callbacks for service binding, passed to bindService(). */ private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance. LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }
Das vorherige Beispiel zeigt, wie sich der Client mithilfe einer Implementierung von
ServiceConnection
und der Callback onServiceConnected()
. Die nächste
enthält weitere Informationen zu diesem Vorgang der Bindung an den Dienst.
Hinweis:Im vorherigen Beispiel hat der Parameter
Die Methode onStop()
hebt die Bindung des Clients an den Dienst auf.
Heben Sie die Bindung von Clients an Dienste zu geeigneten Zeiten auf, wie in den
Zusätzliche Hinweise.
Weiteren Beispielcode finden Sie in der
LocalService.java
-Klasse und die
LocalServiceActivities.java
in ApiDemos.
Messenger verwenden
Wenn Ihr Dienst mit Remote-Prozessen kommunizieren soll, können Sie einen
Messenger
, um die Schnittstelle für Ihren Dienst bereitzustellen. Mit dieser Technik können
Sie führen Interprocess Communication (IPC) durch, ohne AIDL verwenden zu müssen.
Die Verwendung von Messenger
für Ihre Schnittstelle
einfacher als AIDL, da Messenger
-Warteschlangen
an den Dienst senden. Eine reine AIDL-Schnittstelle sendet gleichzeitige Anfragen an den
der dann Multithreading verarbeiten muss.
Bei den meisten Anwendungen muss der Dienst kein Multithreading ausführen, sodass der Dienst mit einem Messenger
jeweils nur einen Aufruf verarbeiten kann. Wenn es wichtig ist,
Wenn Ihr Dienst Multithreaded sein soll, verwenden Sie AIDL, um Ihre Schnittstelle zu definieren.
Hier ist eine Zusammenfassung der Verwendung von Messenger
:
- Der Dienst implementiert eine
Handler
, die für jedes Anruf von einem Kunden. - Der Dienst verwendet den
Handler
, um einenMessenger
zu erstellen Objekt Dies ist ein Verweis aufHandler
. - Der
Messenger
erstellt einIBinder
, das vom Dienst geht vononBind()
an Kunden zurück. - Clients verwenden die
IBinder
, um dieMessenger
zu instanziieren (die auf dieHandler
des Dienstes verweist), die der Client zum SendenMessage
-Objekte für den Dienst. - Der Dienst empfängt jede
Message
in seinerHandler
, genauer gesagt in derhandleMessage()
-Methode.
Auf diese Weise gibt es keine Methoden, die der Client für den Dienst aufrufen kann. Stattdessen
Der Client stellt Nachrichten (Message
-Objekte) zu, die vom Dienst
erhält in
Das ist Handler
.
Hier ist ein einfacher Beispieldienst, der eine Messenger
-Schnittstelle verwendet:
Kotlin
/** Command to the service to display a message. */ private const val MSG_SAY_HELLO = 1 class MessengerService : Service() { /** * Target we publish for clients to send messages to IncomingHandler. */ private lateinit var mMessenger: Messenger /** * Handler of incoming messages from clients. */ internal class IncomingHandler( context: Context, private val applicationContext: Context = context.applicationContext ) : Handler() { override fun handleMessage(msg: Message) { when (msg.what) { MSG_SAY_HELLO -> Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show() else -> super.handleMessage(msg) } } } /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ override fun onBind(intent: Intent): IBinder? { Toast.makeText(applicationContext, "binding", Toast.LENGTH_SHORT).show() mMessenger = Messenger(IncomingHandler(this)) return mMessenger.binder } }
Java
public class MessengerService extends Service { /** * Command to the service to display a message. */ static final int MSG_SAY_HELLO = 1; /** * Handler of incoming messages from clients. */ static class IncomingHandler extends Handler { private Context applicationContext; IncomingHandler(Context context) { applicationContext = context.getApplicationContext(); } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } /** * Target we publish for clients to send messages to IncomingHandler. */ Messenger mMessenger; /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); mMessenger = new Messenger(new IncomingHandler(this)); return mMessenger.getBinder(); } }
Die Methode handleMessage()
in der
Handler
ist der Ort, an dem der Dienst die eingehenden Message
empfängt.
und entscheidet anhand des what
-Mitglieds, was zu tun ist.
Ein Client muss lediglich eine Messenger
auf Basis der vom Dienst zurückgegebenen IBinder
erstellen und eine Nachricht mit send()
senden. Hier sehen Sie als Beispiel eine Aktivität, die an die
-Dienst und stellt die MSG_SAY_HELLO
-Nachricht an den Dienst zu:
Kotlin
class ActivityMessenger : Activity() { /** Messenger for communicating with the service. */ private var mService: Messenger? = null /** Flag indicating whether we have called bind on the service. */ private var bound: Boolean = false /** * Class for interacting with the main interface of the service. */ private val mConnection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = Messenger(service) bound = true } override fun onServiceDisconnected(className: ComponentName) { // This is called when the connection with the service has been // unexpectedly disconnected—that is, its process crashed. mService = null bound = false } } fun sayHello(v: View) { if (!bound) return // Create and send a message to the service, using a supported 'what' value. val msg: Message = Message.obtain(null, MSG_SAY_HELLO, 0, 0) try { mService?.send(msg) } catch (e: RemoteException) { e.printStackTrace() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) } override fun onStart() { super.onStart() // Bind to the service. Intent(this, MessengerService::class.java).also { intent -> bindService(intent, mConnection, Context.BIND_AUTO_CREATE) } } override fun onStop() { super.onStop() // Unbind from the service. if (bound) { unbindService(mConnection) bound = false } } }
Java
public class ActivityMessenger extends Activity { /** Messenger for communicating with the service. */ Messenger mService = null; /** Flag indicating whether we have called bind on the service. */ boolean bound; /** * Class for interacting with the main interface of the service. */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been // established, giving us the object we can use to // interact with the service. We are communicating with the // service using a Messenger, so here we get a client-side // representation of that from the raw IBinder object. mService = new Messenger(service); bound = true; } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected—that is, its process crashed. mService = null; bound = false; } }; public void sayHello(View v) { if (!bound) return; // Create and send a message to the service, using a supported 'what' value. Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); try { mService.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override protected void onStart() { super.onStart(); // Bind to the service. bindService(new Intent(this, MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // Unbind from the service. if (bound) { unbindService(mConnection); bound = false; } } }
Dieses Beispiel zeigt nicht, wie der Dienst dem Client antworten kann.
Wenn Sie möchten, dass die
um zu antworten, müssen Sie auch eine Messenger
im Client erstellen.
Wenn der Client den onServiceConnected()
-Callback empfängt, wird eine Message
an den Dienst gesendet, die Folgendes beinhaltet:
Messenger
des Clients im Parameter replyTo
der Methode send()
.
Ein Beispiel für die bidirektionale Benachrichtigung findest du im
MessengerService.java
(Dienst) und
MessengerServiceActivities.java
-Beispiele (Client).
An einen Dienst binden
Anwendungskomponenten (Clients) können durch Aufrufen von
bindService()
Das Android-
ruft das System die Methode onBind()
des Dienstes auf, die ein IBinder
für die Interaktion mit
für den Dienst.
Die Bindung ist asynchron und bindService()
gibt sofort zurück, ohne IBinder
an
Kundschaft. Um die IBinder
zu erhalten, muss der Client ein
Instanz von ServiceConnection
und übergeben Sie sie an bindService()
. ServiceConnection
enthält eine Callback-Methode, mit der die
Systemaufrufe zur Übermittlung von IBinder
.
Hinweis:Nur Aktivitäten, Dienste und Contentanbieter können verbindliche zu einem Dienst. Eine Bindung an einen Dienst von einem Übertragungsempfänger ist nicht möglich.
So binden Sie Ihren Client an einen Dienst:
- Implementieren Sie
ServiceConnection
.Ihre Implementierung muss zwei Callback-Methoden überschreiben:
onServiceConnected()
- Das System ruft dies auf, um die vom System zurückgegebenen
IBinder
zu senden. mit der MethodeonBind()
des Dienstes. onServiceDisconnected()
- Das Android-System ruft diese Nachricht auf, wenn die Verbindung zum Dienst unerwartet ist zum Beispiel, wenn der Dienst abstürzt oder beendet wird. Dies ist nicht aufgerufen, wenn der hebt die Bindungen auf.
- Rufen Sie
bindService()
auf und übergeben Sie dieServiceConnection
-Implementierung.Hinweis:Wenn die Methode „false“ zurückgibt, Client hat keine gültige Verbindung zum Dienst. Rufen Sie jedoch
unbindService()
in Ihrem Auftraggebenden. Andernfalls unterbindet Ihr Client den Dienst im Leerlauf heruntergefahren. - Wenn das System Ihre
onServiceConnected()
-Callback-Methode aufruft, können Sie Aufrufe an den Dienst senden, indem Sie die von der Schnittstelle definierten Methoden. - Rufen Sie
unbindService()
auf, um die Verbindung zum Dienst zu trennen.Wenn Ihr Client immer noch an einen Dienst gebunden ist, während Ihre Anwendung den Client löscht, werden die Daten gelöscht führt dazu, dass der Client die Bindung aufhebt. Es empfiehlt sich, die Bindung des Clients sofort nach Abschluss des Vorgangs aufzuheben mit dem Dienst interagieren. Dadurch kann der inaktive Dienst heruntergefahren werden. Weitere Informationen Informationen zu geeigneten Zeitpunkten zum Binden und Aufheben der Bindung finden Sie im Abschnitt Zusätzliche Hinweise.
Im folgenden Beispiel wird der Client mit dem zuvor durch
Erweitern der Binder-Klasse, sodass Sie nur die zurückgegebene
IBinder
an die Klasse LocalBinder
und fordern Sie die Instanz LocalService
an:
Kotlin
var mService: LocalService val mConnection = object : ServiceConnection { // Called when the connection with the service is established. override fun onServiceConnected(className: ComponentName, service: IBinder) { // Because we have bound to an explicit // service that is running in our own process, we can // cast its IBinder to a concrete class and directly access it. val binder = service as LocalService.LocalBinder mService = binder.getService() mBound = true } // Called when the connection with the service disconnects unexpectedly. override fun onServiceDisconnected(className: ComponentName) { Log.e(TAG, "onServiceDisconnected") mBound = false } }
Java
LocalService mService; private ServiceConnection mConnection = new ServiceConnection() { // Called when the connection with the service is established. public void onServiceConnected(ComponentName className, IBinder service) { // Because we have bound to an explicit // service that is running in our own process, we can // cast its IBinder to a concrete class and directly access it. LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } // Called when the connection with the service disconnects unexpectedly. public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "onServiceDisconnected"); mBound = false; } };
Mit diesem ServiceConnection
kann sich der Client an einen Dienst binden
indem Sie
es an bindService()
, wie im folgenden Beispiel gezeigt:
Kotlin
Intent(this, LocalService::class.java).also { intent -> bindService(intent, connection, Context.BIND_AUTO_CREATE) }
Java
Intent intent = new Intent(this, LocalService.class); bindService(intent, connection, Context.BIND_AUTO_CREATE);
- Der erste Parameter von
bindService()
ist einIntent
, die den zu bindenden Dienst explizit benennen.Achtung:Wenn Sie einen Intent zur Bindung an einen
Service
, achte darauf, dass deine App sicher ist, indem du ein explizites die Nutzerabsicht verstehen. Die Verwendung eines impliziten Intents zum Starten eines Dienstes Sicherheitsrisiko, da Sie nicht sicher sind, welcher Dienst auf den Intent reagiert, und der Nutzer kann nicht sehen, welcher Dienst gestartet wird. Ab Android 5.0 (API-Level 21) das System löst eine Ausnahme aus, wenn SiebindService()
aufrufen mit einer impliziten Absicht. - Der zweite Parameter ist das Objekt
ServiceConnection
. - Der dritte Parameter ist ein Flag, das Optionen für die Bindung angibt – normalerweise
BIND_AUTO_CREATE
, um den Dienst zu erstellen, falls noch nicht geschehen. zum Leben erweckt wird. Andere mögliche Werte sindBIND_DEBUG_UNBIND
,BIND_NOT_FOREGROUND
oder0
für keine.
Zusätzliche Anmerkungen
Hier sind einige wichtige Hinweise zur Bindung an einen Dienst:
DeadObjectException
-Ausnahmen immer erfassen, die ausgelöst werden wenn die Verbindung unterbrochen wird. Dies ist die einzige Ausnahme, die von Remote-Methoden ausgelöst wird.- Objekte werden prozessübergreifend gezählt.
- Normalerweise koppeln Sie das Binden und das Aufheben der Bindung während der
Abgleichen der Zeitpunkte des Hochfahrens und Entfernens von Daten im Lebenszyklus des Kunden, wie in den
folgende Beispiele:
<ph type="x-smartling-placeholder">
- </ph>
- Wenn Sie nur mit dem Dienst interagieren müssen, während Ihre Aktivität sichtbar ist, binden Sie die Bindung während
onStart()
und heben Sie die Bindung währendonStop()
auf. - Wenn Sie möchten, dass Ihre Aktivität auch dann Antworten erhält, wenn sie im
Hintergrund, während
onCreate()
binden und Bindung aufheben imonDestroy()
. Beachten Sie, dass dies impliziert, muss der Dienst während seiner gesamten Ausführung – auch im Hintergrund – genutzt werden. sich der Dienst in einem anderen Prozess befindet, steigern Sie das Gewicht des Prozesses dass sie vom System abgerissen werden.
Hinweis:Normalerweise wird das Binden nicht angewendet und die Bindung wird aufgehoben. während der
onResume()
- undonPause()
-Callbacks deiner Aktivität, da diese Callbacks an jedem Tag Lebenszykluswechsel. Begrenzen Sie die Verarbeitung an diesen Übergängen auf ein Minimum.Wenn außerdem mehrere Aktivitäten in Ihrer Anwendung an denselben Dienst gebunden sind und es eine Übergang zwischen könnte der Dienst zerstört und als aktueller Dienst neu erstellt werden, Bindungen von Aktivitäten aufheben (während der Pause) vor der nächsten Bindung (während des Fortfahrens). Bei diesem Aktivitätswechsel Informationen zur Koordinierung ihres Lebenszyklus durch Aktivitäten finden Sie unter Aktivitätslebenszyklus.
- Wenn Sie nur mit dem Dienst interagieren müssen, während Ihre Aktivität sichtbar ist, binden Sie die Bindung während
Weiteren Beispielcode, der die Bindung an einen Dienst zeigt, finden Sie in der
RemoteService.java
in ApiDemos.
Lebenszyklus eines gebundenen Dienstes verwalten
Wenn ein Dienst von allen Clients getrennt wird, wird er vom Android-System gelöscht
(es sei denn, es wurde mit
startService()
.
Sie müssen den Lebenszyklus
Ihres Dienstes also nicht verwalten,
ein gebundener Dienst. Das Android-System verwaltet dies
für Sie basierend auf
unabhängig davon, ob sie an
Clients gebunden ist.
Wenn Sie sich jedoch dafür entscheiden, die Callback-Methode onStartCommand()
zu implementieren, müssen Sie den Dienst ausdrücklich beenden, da das Ereignis
Der Dienst gilt jetzt als gestartet. In diesem Fall wird der Dienst ausgeführt, bis der Dienst
stoppt sich selbst mit stopSelf()
oder eine andere Komponente ruft stopService()
auf, unabhängig davon, ob sie an irgendwelche
Kundschaft.
Wenn Ihr Dienst gestartet wird und Bindung akzeptiert, geschieht außerdem, wenn das System beim Aufruf von
onUnbind()
-Methode festlegen, können Sie optional
true
, wenn Sie einen Aufruf von onRebind()
erhalten möchten, wenn das nächste Mal ein Client eine Bindung an den Dienst herstellt. onRebind()
gibt eine ungültige Antwort zurück, aber der Kunde erhält das IBinder
-Objekt trotzdem mit seiner
onServiceConnected()
-Callback.
Die folgende Abbildung veranschaulicht die Logik für diese Art von Lebenszyklus.
Weitere Informationen zum Lebenszyklus eines gestarteten Dienstes finden Sie in der Dienstübersicht.