Un servicio vinculado es el servidor de una interfaz cliente-servidor. Permite que los componentes (como actividades) se vinculen con el servicio, envíen solicitudes, reciban respuestas y establezcan comunicaciones entre procesos (IPC). Un servicio vinculado, por lo general, solo está activo mientras le presta servicio a otro componente de la aplicación y no se ejecuta en segundo plano indefinidamente.
En este documento, se describe cómo crear un servicio vinculado, además de cómo establecer una vinculación con el servicio desde otros componentes de la aplicación. A fin de obtener información adicional sobre los servicios en general (por ejemplo, cómo enviar notificaciones desde un servicio, cómo configurar el servicio para que se ejecute en primer plano, etc.), consulta el documento Servicios.
Conceptos básicos
Un servicio vinculado es una implementación de la clase Service
que permite que otras aplicaciones se vinculen e interactúen con él. Para vincular un servicio, debes implementar el método de devolución de llamada onBind()
. Este método muestra un objeto IBinder
que define la interfaz de programación que los clientes pueden usar para interactuar con el servicio.
Cómo crear una vinculación con un servicio iniciado
Como ya se explicó en el documento Servicios, puedes crear un servicio que ya se haya iniciado y vinculado. Es decir, el servicio se puede iniciar llamando a startService()
, lo que permite que el servicio se ejecute indefinidamente, y también puedes permitir que un cliente establezca una vinculación con el servicio llamando a bindService()
.
Si permites que tu servicio se inicie y se vincule, entonces, cuando se haya iniciado el servicio, el sistema Servicios lo destruirá cuando se desvinculen todos los clientes.
En su lugar, debes detener explícitamente el servicio llamando a stopSelf()
o stopService()
.
Si bien generalmente implementas onBind()
o onStartCommand()
, a veces es necesario implementar ambos. Por ejemplo, para un reproductor de música, podría ser útil permitir que su servicio se ejecute de manera indefinida y también proporcionar capacidad de creación de vinculaciones. De esta manera, una actividad puede iniciar el servicio para que reproduzca música y que la música continúe reproduciéndose incluso cuando el usuario salga de la aplicación. Cuando el usuario regrese a la aplicación, la actividad podrá vincularse al servicio para volver a tener el control de la reproducción.
Para obtener más información sobre el ciclo de vida del servicio cuando se agrega una vinculación con un servicio iniciado, consulta Cómo administrar el ciclo de vida de un servicio vinculado.
Un cliente se vincula a un servicio llamando a bindService()
. Cuando lo hace, debe implementar ServiceConnection
, que supervisa la conexión con el servicio. El valor que se muestra de bindService()
indica si el servicio solicitado existe y si se le permite al cliente acceder a él. Cuando el sistema Android crea la conexión entre el cliente y el servicio, llama a onServiceConnected()
en ServiceConnection
. El método onServiceConnected()
incluye un argumento IBinder
que el cliente utiliza para comunicarse con el servicio vinculado.
Puedes conectar varios clientes a un servicio simultáneamente. Sin embargo, el sistema almacena en caché el canal de comunicación del servicio IBinder
.
En otras palabras, el sistema llama al método onBind()
del servicio para generar el IBinder
solo cuando se vincula el primer cliente. El sistema entonces entrega el mismo IBinder
a todos los clientes adicionales que se vinculan a ese mismo servicio, sin volver a llamar a onBind()
.
Cuando se desvincula el último cliente del servicio, el sistema destruye el servicio (a menos que este también haya sido iniciado por startService()
).
La parte más importante de la implementación de tu servicio vinculado es definir la interfaz que mostrará tu método de devolución de llamada onBind()
. En la próxima sección, se analizan varias formas diferentes en las que puedes definir la interfaz de tu servicio IBinder
.
Cómo crear un servicio enlazado
Al crear un servicio que proporciona la capacidad de crear una vinculación, debes proporcionar un IBinder
que contenga la interfaz de programación que los clientes pueden usar para interactuar con el servicio. Puedes definir la interfaz de las siguientes tres maneras:
- Extender la clase Binder
- Si tu servicio es privado para tu propia aplicación y se ejecuta en el mismo proceso que el cliente (que es lo común), deberías crear tu interfaz extendiendo la clase
Binder
y mostrando una instancia de ella desdeonBind()
. El cliente recibe elBinder
y puede usarlo para acceder directamente a métodos públicos disponibles en la implementación deBinder
oService
.Esta es la técnica preferida cuando tu servicio es solo un trabajador en segundo plano de tu propia aplicación. El único motivo por el que no deberías crear tu interfaz de esta manera es que otras aplicaciones usen tu servicio o que este se use entre procesos independientes.
- Utilizar un objeto Messenger
- Si necesitas que tu interfaz funcione en diferentes procesos, puedes crear una para el servicio con un
Messenger
. De esta manera, el servicio define unHandler
que responde a diferentes tipos de objetosMessage
. EsteHandler
es la base para unMessenger
que luego pueda compartir unIBinder
con el cliente y permitir que el cliente envíe comandos al servicio usando objetosMessage
. Además, el cliente puede definir unMessenger
propio de modo que el servicio pueda devolver mensajes.Esta es la manera más sencilla de establecer comunicación entre procesos (IPC), ya que
Messenger
pone en cola todas las solicitudes en un solo subproceso a fin de que no debas diseñar tu servicio de modo que sea seguro para subprocesos. - Utilizar AIDL
- El Lenguaje de definición de la interfaz de Android (AIDL) realiza todo el trabajo de descomposición de objetos en primitivas que el sistema operativo puede comprender y los ordena entre procesos para establecer IPC. La técnica anterior, que utiliza un
Messenger
, usa AIDL como estructura subyacente. Como se indicó antes, elMessenger
crea una cola de todas las solicitudes del cliente de modo que el servicio reciba las solicitudes de a una. Sin embargo, si quieres que tu servicio administre varias solicitudes de forma simultánea, puedes usar AIDL directamente. En ese caso, tu servicio debe ser seguro para subprocesos y capaz de administrar varios de ellos.Para usar el AIDL de forma directa, debes crear un archivo
.aidl
que defina la interfaz de programación. Las herramientas del SDK de Android usan ese archivo para generar una clase abstracta que implemente la interfaz y manipule la IPC, que luego podrás extender en tu servicio.
Nota: La mayoría de las aplicaciones no deben usar AIDL para crear un servicio vinculado, ya que podría requerir capacidades de ejecución de varios subprocesos y dar lugar a una implementación más complicada. Como tal, AIDL no es conveniente para la mayoría de las aplicaciones, y en este documento no se explica cómo usarlo en tu servicio. Si crees con firmeza que necesitas usar AIDL de forma directa, lee el documento AIDL.
Cómo extender la clase Binder
Si solo la aplicación local usa tu servicio y este no necesita ejecutarse en diferentes procesos, puedes implementar tu propia clase de Binder
que le proporcione al cliente acceso directo a los métodos públicos incluidos en el servicio.
Nota: Esto funciona únicamente si el cliente y el servicio se encuentran en la misma aplicación y el mismo proceso, que es lo más común. Por ejemplo, esto puede funcionar bien para una aplicación de música que necesite vincular una actividad con su propio servicio que reproduce contenido en segundo plano.
A continuación, te indicamos cómo configurarlo:
- En tu servicio, crea una instancia de
Binder
que haga lo siguiente:- Contenga métodos públicos que el cliente pueda llamar
- Muestre la instancia
Service
actual, que tiene métodos públicos que el cliente puede llamar - Muestre una instancia de otra clase alojada por el servicio con métodos públicos que el cliente pueda llamar
- Muestre esta instancia
Binder
desde el método de devolución de llamadaonBind()
- En el cliente, reciba
Binder
del método de devolución de llamadaonServiceConnected()
y realice llamadas al servicio vinculado usando los métodos proporcionados
Nota: El servicio y el cliente deben estar en la misma aplicación para que el cliente pueda convertir el objeto mostrado y llamar a sus API de forma correcta. El servicio y el cliente también deben estar en el mismo proceso, ya que esta técnica no realiza ningún tipo de ordenamiento entre procesos.
Por ejemplo, aquí hay un servicio que les brinda a los clientes acceso a métodos del servicio a través de la implementación de un Binder
:
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
proporciona el método getService()
para que los clientes obtengan la instancia actual de LocalService
. Esto permite a los clientes llamar a métodos públicos en el servicio. Por ejemplo, los clientes pueden llamar a getRandomNumber()
desde el servicio.
A continuación, se proporciona una actividad que se vincula a LocalService
y llama a getRandomNumber()
cuando se hace clic en un botón:
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 were something that might hang, then this request should // occur 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 were something that might hang, then this request should // occur 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; } }; }
En el ejemplo anterior, se muestra la manera en que el cliente establece una vinculación con el servicio usando una implementación de ServiceConnection
y la devolución de llamada onServiceConnected()
. En la siguiente sección, se proporciona más información sobrde este proceso de vinculación con el servicio.
Nota: En el ejemplo anterior, el método onStop()
desvincula al cliente del servicio. Los clientes se deben desvincular de los servicios en el momento apropiado, como se discute en Notas adicionales.
Para acceder a otros ejemplos de código, consulta las clases LocalService.java
y LocalServiceActivities.java
en ApiDemos.
Utilizar un objeto Messenger
Si necesitas que tu servicio se comunique con procesos remotos, puedes usar un Messenger
a fin de proporcionar la interfaz para tu servicio. Esta técnica te permite establecer comunicación entre procesos (IPC) sin la necesidad de usar AIDL.
El uso de un Messenger
para tu interfaz es más sencillo que el uso de AIDL, ya que Messenger
pone en cola todas las llamadas al servicio. Una interfaz de AIDL pura envía solicitudes simultáneas al servicio, que a su vez debe administrar varios subprocesos.
Para la mayoría de las aplicaciones, el servicio no necesita ejecutar varios subprocesos; por lo tanto, el uso de un Messenger
permite que el servicio administre una llamada por vez. Si es importante que tu servicio ejecute varios subprocesos, debes usar AIDL para definir tu interfaz.
Aquí te mostramos un resumen de cómo usar un Messenger
:
- El servicio implementa un
Handler
que recibe una devolución por cada llamada de un cliente. - El servicio usa el
Handler
para crear un objetoMessenger
(que es una referencia alHandler
). - El
Messenger
crea unIBinder
que el servicio muestra a los clientes desdeonBind()
. - Los clientes usan el
IBinder
para crear instancias delMessenger
(que hace referencia alHandler
del servicio), que el cliente usa para enviar objetosMessage
al servicio. - El servicio recibe cada
Message
en suHandler
; específicamente, en el métodohandleMessage()
.
De esta manera, no hay métodos que el cliente pueda usar para llamar al servicio. En su lugar, el cliente envía mensajes (objetos Message
) que el servicio recibe en su Handler
.
Aquí te mostramos un ejemplo sencillo de servicio que usa una interfaz Messenger
:
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(); } }
Observa que el método handleMessage()
de Handler
es donde el servicio recibe el Message
entrante y decide qué hacer en función del miembro de what
.
Todo lo que el cliente debe hacer es crear un Messenger
en función del IBinder
que muestra el servicio y enviar un mensaje con send()
. Por ejemplo, esta es una actividad simple que se vincula con el servicio y le envía el mensaje MSG_SAY_HELLO
:
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; } } }
Ten en cuenta que este ejemplo no muestra cómo el servicio puede responderle al cliente.
Si quieres que el servicio responda, también deberás crear un Messenger
en el cliente.
Cuando el cliente recibe la devolución de llamada onServiceConnected()
, envía un Message
al servicio que incluye el Messenger
del cliente en el parámetro replyTo
del método send()
.
Puedes ver la manera de proporcionar un sistema de mensajería bidireccional en los ejemplos de MessengerService.java
(servicio) y MessengerServiceActivities.java
(cliente).
Cómo crear una vinculación con un servicio
Los componentes de la aplicación (clientes) pueden establecer una vinculación con un servicio llamando a bindService()
. Luego, el sistema Android llama al método onBind()
del servicio, que muestra un IBinder
para interactuar con él.
La vinculación es asíncrona, y bindService()
se muestra inmediatamente sin mostrarle el IBinder
al cliente. Para recibir el IBinder
, el cliente debe crear una instancia de ServiceConnection
y pasarla a bindService()
. ServiceConnection
incluye un método de devolución de llamada al que el sistema llama para enviar el IBinder
.
Nota: Solo las actividades, los servicios y los proveedores de contenido pueden establecer vinculaciones con un servicio; no puedes establecer vinculaciones con un servicio desde un receptor de emisión.
Para establecer una vinculación con un servicio desde tu cliente, debes hacer lo siguiente:
- Implementa
ServiceConnection
.Tu implementación debe anular dos métodos de devolución de llamada:
onServiceConnected()
- El sistema lo llama para enviar el
IBinder
que muestra el métodoonBind()
del servicio. onServiceDisconnected()
- El sistema Android lo llama cuando se pierde de forma inesperada la conexión con el servicio, por ejemplo, cuando el servicio falla o se detiene. No lo llama cuando se desvincula el cliente.
- Llama a
bindService()
y pasa la implementación deServiceConnection
.Nota: Si el método muestra un valor falso, significa que tu cliente no tiene una conexión válida con el servicio. Sin embargo, tu cliente debe seguir llamando a
unbindService()
; de lo contrario, evitará que finalice el servicio cuando esté inactivo. - Cuando el sistema llama a tu método de devolución de llamada
onServiceConnected()
, puedes comenzar a realizar llamadas al servicio usando los métodos definidos por la interfaz. - Para desconectarte del servicio, llama a
unbindService()
.Si tu cliente aún está vinculado a un servicio cuando tu app destruye el cliente, la destrucción hace que se desvincule el cliente. La práctica recomendada es desvincular el cliente tan pronto como acabe la interacción con el servicio. Hacer eso permite que se cierre el servicio inactivo. Si deseas obtener más información sobre momentos apropiados para la vinculación y la desvinculación, consulta Notas adicionales.
Por ejemplo, el siguiente fragmento de código conecta al cliente con el servicio antes creado extendiendo la clase Binder; por lo tanto, lo único que debe hacer es transmitir el IBinder
mostrado en la clase LocalBinder
y solicitar la instancia LocalService
:
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; } };
Con este ServiceConnection
, el cliente puede establecer una vinculación con un servicio pasándolo a bindService()
, como se muestra en el siguiente ejemplo:
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);
- El primer parámetro de
bindService()
es unIntent
que menciona explícitamente el servicio para vincular.Precaución: Si utilizas un intent para la vinculación con un
Service
, asegúrate de que la app sea segura mediante un intent explícito. El uso de un intent explícito para iniciar un servicio es un riesgo de seguridad porque no puedes estar seguro de qué servicio responderá al intent, y el usuario no puede ver qué servicio se inicia. A partir de Android 5.0 (API nivel 21), el sistema lanza una excepción si llamas abindService()
con un intent implícito. - El segundo parámetro es el objeto
ServiceConnection
. - El tercer parámetro es un indicador que contiene opciones para el enlace. Normalmente, debería ser
BIND_AUTO_CREATE
para crear el servicio si aún no está activo. Otros valores posibles sonBIND_DEBUG_UNBIND
yBIND_NOT_FOREGROUND
, o bien0
para ninguno.
Notas adicionales
Aquí te proporcionamos algunas notas importantes acerca de cómo establecer enlaces con un servicio:
- Siempre debes capturar excepciones
DeadObjectException
, que se producen cuando se pierde la conexión. Esta es la única excepción que producen los métodos remotos. - Los objetos se cuentan como referencia entre procesos.
- Normalmente, debes sincronizar la vinculación y la desvinculación durante la introducción y la anulación de correspondencias del ciclo de vida del cliente, como se describe en los siguientes ejemplos:
- Si debes interactuar con el servicio solo mientras tu actividad esté visible, debes establecer la vinculación durante
onStart()
y deshacerla duranteonStop()
. - Si quieres que tu actividad reciba respuestas aunque esté detenida en segundo plano, puedes establecer la vinculación durante
onCreate()
y deshacerla duranteonDestroy()
. Ten en cuenta que esto implica que tu actividad necesita usar el servicio todo el tiempo que se esté ejecutando (incluso en segundo plano), por lo que si el servicio se encuentra en otro proceso, aumentas el peso del proceso y es muy probable que el sistema lo cierre.
Nota: Generalmente, no debes realizar ni deshacer vinculaciones durante los procesos de
onResume()
yonPause()
de tu actividad, ya que estas devoluciones de llamada tienen lugar en todas las transiciones del ciclo de vida y debes minimizar al máximo el procesamiento que se produce en esas transiciones. Asimismo, si varias actividades de tu aplicación se vinculan con el mismo servicio y se produce una transición entre dos de ellas, es posible que el servicio se destruya y se recree cuando se desvincula la actividad actual (durante una pausa) y antes de que se vincule la siguiente (durante la reanudación). (Esta transición de una actividad en relación con cómo las actividades coordinan su ciclo de vida se describe en el documento Actividades). - Si debes interactuar con el servicio solo mientras tu actividad esté visible, debes establecer la vinculación durante
Para acceder a otros ejemplos de código en los que se muestre la manera de establecer una vinculación con un servicio, lee la clase RemoteService.java
en ApiDemos.
Cómo administrar el ciclo de vida de un servicio enlazado
Cuando se desvincula un servicio de todos los clientes, el sistema Android lo destruye (a menos que también se haya iniciado con una llamada de startService()
). De este modo, no necesitas administrar el ciclo de vida de tu servicio si este es puramente un servicio de vinculación; el sistema Android lo administra por ti en función de si está vinculado a algún cliente.
No obstante, si decides implementar el método de devolución de llamada onStartCommand()
, debes detener el servicio de forma explícita, ya que el servicio ahora se considera iniciado. En este caso, el servicio se ejecuta hasta que se detenga por sí mismo con stopSelf()
o cuando otro componente llame a stopService()
, independientemente de que esté vinculado o no a algún cliente.
Además, si se inicia tu servicio y este acepta la vinculación, entonces, cuando el sistema llame a tu método onUnbind()
, puedes mostrar true
si deseas recibir una llamada para onRebind()
la próxima vez que un cliente establezca una vinculación con el servicio. onRebind()
muestra void, pero el cliente de todos modos recibe el IBinder
en su devolución de llamada onServiceConnected()
.
En la figura que aparece a continuación, se ilustra la lógica para este tipo de ciclo de vida.

Figura 1: Ciclo de vida para un servicio iniciado que también admite vinculación
Para obtener más información sobre el ciclo de vida de un servicio iniciado, lee el documento Servicios.