Un Service
es un
componente de la aplicación que puede realizar
para las operaciones
de larga duración en segundo plano. No proporciona una interfaz de usuario. Una vez
iniciar, un servicio puede seguir funcionando durante un tiempo, incluso después de que el usuario cambie a otro
y mantener la integridad de su aplicación. Además, un componente puede vincularse a un servicio para interactuar con él e incluso realizar
comunicación entre procesos (IPC). Por ejemplo, un servicio puede manejar transacciones de red, reproducir
música, realizar E/S de archivos o interactuar con un proveedor de contenido, todo en segundo plano.
Precaución: Un servicio se ejecuta en el subproceso principal de su hosting proceso; El servicio no crea su propio subproceso ni no. se ejecuta en un proceso independiente, a menos que especifiques uno diferente. Debes ejecutar las operaciones de bloqueo en un subproceso separado dentro del servicio para evitar el uso de Application Errores que no responden (ANR).
Tipos de servicios
Estos son los tres tipos diferentes de servicios:
- Primer plano
-
Un servicio en primer plano realiza una operación notoria para el usuario. Por ejemplo, una aplicación de audio utilizaría un servicio en primer plano para reproducir una pista de audio. Los servicios en primer plano deben mostrar una notificación. Los servicios en primer plano continúan ejecutándose incluso cuando el usuario no interactúa. con la app.
Cuando usas un servicio en primer plano, debes mostrar una notificación para que los usuarios sepan activamente que el servicio se está ejecutando. Esta notificación no puede a menos que el servicio se detenga o se elimine de la primer plano.
Más información para configurar servicios en primer plano en tus .
Nota: El elemento La API de WorkManager ofrece una forma flexible de programar tareas. pueda ejecutar estos trabajos como servicios en primer plano si es necesario. En muchos casos, usar Es preferible usar WorkManager antes que usar los servicios en primer plano directamente.
- Información general
- Un servicio en segundo plano realiza una operación que no detecta directamente
del usuario. Por ejemplo, si una app
usa un servicio para compactar su almacenamiento
que suele ser un servicio en segundo plano.
Nota: Si tu app tiene como objetivo el nivel de API 26 o uno superior, el sistema impone restricciones sobre la ejecución en segundo plano. de Google Cloud cuando la app no está en primer plano. En la mayoría situaciones, por ejemplo, no deberías a la información de ubicación segundo plano. En cambio, programar tareas con WorkManager
- Enlace
- Un servicio está vinculado cuando un componente de la aplicación se vincula a él llamando a
bindService()
. Un servicio vinculado ofrece una conexión cliente-servidor que permite que los componentes interactúen con el servicio, envíen solicitudes y reciban resultados, e incluso hacerlo en todos los procesos con la comunicación entre procesos (IPC). Un servicio vinculado solo se ejecuta siempre que otro componente de la aplicación esté vinculado a él. Múltiples componentes pueden vincularse el servicio a la vez, pero cuando todos se desvinculan, el servicio se destruye.
Aunque esta documentación generalmente analiza por separado los servicios iniciados y vinculados,
su servicio puede funcionar en ambos sentidos: puede iniciarse (para ejecutarse de forma indefinida) y también permitir
la vinculación. Solo es cuestión de implementar un par de métodos de devolución de llamada: onStartCommand()
para permitir que los componentes lo inicien y onBind()
para permitir la vinculación.
Independientemente de si tu servicio está iniciado, vinculado o ambos, cualquier componente de la aplicación
puede usar el servicio (incluso desde otra aplicación) de la misma manera que cualquier componente puede usar
una actividad, iniciándola con un Intent
. Sin embargo, puedes declarar
el servicio como privado en el archivo de manifiesto y bloquear el acceso de otras aplicaciones.
Este tema se analiza más detalladamente en la sección Declaración del servicio en la
.
Diferencia entre un servicio y un subproceso
Un servicio es simplemente un componente que puede ejecutarse en segundo plano, incluso cuando el usuario que está interactuando con tu aplicación, por lo que debes crear un servicio solo si eso es lo que que necesitan tus usuarios.
Si debes realizar un trabajo fuera de tu subproceso principal, pero solo mientras el usuario interactúa
con tu aplicación, debes crear un subproceso nuevo en el contexto de otra aplicación
este componente. Por ejemplo, si quieres reproducir música, pero solo mientras se ejecuta tu actividad,
puedes crear un subproceso en onCreate()
comenzarás a ejecutarla en onStart()
,
y deténgalo en onStop()
.
También considera usar grupos de subprocesos y ejecutores del paquete java.util.concurrent
.
o corrutinas de Kotlin en lugar de
Thread
. Consulta la
Subprocesos en Android para obtener más información
y mueve la ejecución a subprocesos en segundo plano.
Recuerda que, si usas un servicio, este se ejecutará en el subproceso principal de tu aplicación de forma predeterminada, por lo que aún debes crear un nuevo subproceso dentro del servicio si realiza tareas intensivas o de bloqueo de contenido.
Conceptos básicos
Para crear un servicio, debes crear una subclase de Service
o usar una
de sus subclases existentes. En tu implementación, debes anular algunos métodos de devolución de llamada que
administrar aspectos clave del ciclo de vida
del servicio y proporcionar un mecanismo
enlazarse con el servicio, si corresponde. Estos son los métodos de devolución de llamada más importantes que debes
anulación:
onStartCommand()
- El sistema invoca a este método llamando a
startService()
cuando otro componente (como una actividad) solicita que se inicie el servicio. Cuando se ejecuta este método, el servicio se inicia y puede ejecutarse en la en segundo plano indefinidamente. Si implementas esto, será tu responsabilidad detener el servicio cuando se completa su trabajo llamando astopSelf()
ostopService()
. Si solo quieres proporcionar enlaces, no debes necesitas para implementar este método. onBind()
- El sistema invoca a este método llamando a
bindService()
cuando otro componente quiere vincularse con el servicio (por ejemplo, para ejecutar RPC). En la implementación de este método, debes proporcionar una interfaz que los clientes usar para comunicarse con el servicio mostrando unIBinder
. Siempre debes implementar este método; Sin embargo, si no deseas permitir la vinculación, debes mostrar null. onCreate()
- El sistema invoca a este método para realizar procedimientos de configuración únicos cuando el servicio se
creados inicialmente (antes de llamar a
onStartCommand()
oonBind()
). Si el servicio ya se está ejecutando, este método no llamado. onDestroy()
- El sistema invoca a este método cuando el servicio ya no se usa y se está destruyendo. Tu servicio debería implementar esto para limpiar los recursos, como subprocesos, registros objetos de escucha o receptores. Esta es la última llamada que el servicio recibe.
Si un componente inicia el servicio llamando a startService()
(lo que da como resultado una llamada a onStartCommand()
), el servicio
continúa ejecutándose hasta que se detiene a sí mismo con stopSelf()
o con otro
componente lo detiene llamando a stopService()
.
Si un componente llama
bindService()
para crear el servicio y no se llama a onStartCommand()
, el servicio se ejecuta
solo mientras el componente esté vinculado a él. Una vez que el servicio se desenlaza de todos sus clientes,
el sistema la destruye.
El sistema Android detiene un servicio solo cuando hay poca memoria y debe recuperar el sistema
para la actividad que tiene el enfoque del usuario. Si el servicio está vinculado a una actividad que tiene acceso
concentración, es menos probable que lo maten; si se declara que el servicio se ejecuta en primer plano, rara vez se cierra.
Si el servicio se inicia y es de larga duración, el sistema baja su posición
en la lista de tareas en segundo plano con el paso del tiempo, y el servicio se vuelve muy susceptible de
hasta el final: si se inicia tu servicio, debes diseñarlo para que administre los reinicios con facilidad
por el sistema. Si el sistema finaliza su servicio, lo reinicia en cuanto los recursos quedan
disponible, pero esto también depende del valor que muestres desde onStartCommand()
. Más información
acerca de cuándo el sistema puede destruir un servicio; consulta el artículo Procesos y subprocesos
.
En las siguientes secciones, verás cómo puedes crear la
startService()
y
bindService()
y cómo usarlos
de otros componentes de la aplicación.
Declarar un servicio en el manifiesto
Debes declarar todos los servicios en el directorio del mismo modo que con las actividades y otros componentes.
Para declarar tu servicio, agrega un elemento <service>
.
como hijo de <application>
. A continuación, se muestra un ejemplo:
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
Consulta el elemento <service>
.
para obtener más información sobre la declaración de tu servicio en el manifiesto.
Hay otros atributos que puedes incluir en el elemento <service>
para
definen propiedades como los permisos necesarios para iniciar el servicio y el proceso en
la que el servicio debe ejecutar. La android:name
es el único atributo obligatorio, que especifica el nombre de la clase del servicio. Después del
cuando publiques tu aplicación, no modifiques este nombre para evitar el riesgo de romper
debido a la dependencia de intents explícitas para iniciar o enlazar el servicio (lee la entrada de blog Cosas
que no puede cambiar).
Precaución: Para garantizar que tu app sea segura, usa siempre un
explícito cuando inicies un Service
y no declares filtros de intents para
tus servicios. El uso de un intent implícito para iniciar un servicio es un riesgo de seguridad porque no puedes
el servicio que responde al intent, y el usuario no puede ver
comienza el ciclo de vida. A partir de Android 5.0 (nivel de API 21), el sistema lanza una excepción si llamas
bindService()
con un intent implícito
Para asegurarte de que el servicio esté disponible solo para tu app, debes
incluido android:exported
y configúralo como false
. Esto evita que otras apps inicien tu
incluso cuando se usa un intent explícito.
Nota:
Los usuarios pueden ver qué servicios se ejecutan en sus dispositivos. Si ven
pero no reconocen o en el que no confían, pueden detenerlo. En
para evitar que los usuarios detengan accidentalmente tu servicio, debes
para agregar
android:description
al
<service>
en el manifiesto de la app. En la descripción
Proporciona una oración breve que explique qué hace el servicio y los beneficios que ofrece.
que proporciona.
Crear un servicio iniciado
Un servicio iniciado es un servicio que otro componente inicia llamando a startService()
, lo que da como resultado una llamada a la
onStartCommand()
.
Cuando se inicia un servicio, tiene un ciclo de vida que es independiente del
y el componente que lo inició. El servicio puede ejecutarse en segundo plano de manera indefinida, incluso si
se destruye el componente que lo inició. Por lo tanto, el servicio debería detenerse a sí mismo cuando
se completa llamando a stopSelf()
, o bien otro componente puede
y detenerla llamando a stopService()
.
Un componente de la aplicación, como una actividad, puede iniciar el servicio llamando a startService()
y pasando un Intent
.
que especifique el servicio e incluya datos para que el servicio pueda utilizar. El servicio recibe
este Intent
en el método onStartCommand()
.
Por ejemplo, imagina que una actividad necesita guardar datos en una base de datos en línea. La actividad
Puedes iniciar un servicio complementario y enviarle los datos que se guardarán pasando un intent a startService()
. El servicio recibe el intent en onStartCommand()
, se conecta a Internet y realiza las
transacción de base de datos. Cuando se completa la transacción, el servicio se detiene a sí mismo y
antes de que se destruyan.
Precaución: Un servicio se ejecuta en el mismo proceso que la aplicación. en el que está declarada y en el subproceso principal de esa aplicación de forma predeterminada. Si tu servicio realiza operaciones intensivas o de bloqueo mientras el usuario interactúa con una actividad de la misma de la aplicación, el servicio ralentiza el rendimiento de la actividad. Para evitar que la aplicación se vea afectada rendimiento, inicia un subproceso nuevo dentro del servicio.
La clase Service
es la base
para todos los servicios. Cuando extiendes esta clase, es importante crear un subproceso nuevo en el que
el servicio pueda completar todo su trabajo; este usa el subproceso principal de tu aplicación
de forma predeterminada, lo que puede ralentizar el rendimiento de cualquier actividad que ejecute tu aplicación.
El framework de Android también proporciona IntentService
.
subclase de Service
que usa un
subproceso de trabajo para manejar todas las solicitudes de inicio, una a la vez. Usar esta clase no es
recomendado para las apps nuevas, ya que no funcionará bien a partir de Android 8 Oreo, debido al
introducción a los límites de ejecución en segundo plano
Además, dejó de estar disponible a partir de Android 11.
Puedes usar JobIntentService como
reemplazo de IntentService
, que es compatible con versiones más recientes de Android.
En las siguientes secciones, se describe cómo implementar tu propio servicio personalizado. Sin embargo, deberías te recomendamos que uses WorkManager en la mayoría de los casos de uso. Consulta la guía para el procesamiento en segundo plano en Android. para ver si hay una solución que se adapte a tus necesidades.
Extender la clase Service
Puedes extender la clase Service
para manejar cada intent entrante. A continuación, se muestra cómo se vería una implementación básica:
Kotlin
class HelloService : Service() { private var serviceLooper: Looper? = null private var serviceHandler: ServiceHandler? = null // Handler that receives messages from the thread private inner class ServiceHandler(looper: Looper) : Handler(looper) { override fun handleMessage(msg: Message) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000) } catch (e: InterruptedException) { // Restore interrupt status. Thread.currentThread().interrupt() } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1) } } override fun onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND).apply { start() // Get the HandlerThread's Looper and use it for our Handler serviceLooper = looper serviceHandler = ServiceHandler(looper) } } override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show() // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job serviceHandler?.obtainMessage()?.also { msg -> msg.arg1 = startId serviceHandler?.sendMessage(msg) } // If we get killed, after returning from here, restart return START_STICKY } override fun onBind(intent: Intent): IBinder? { // We don't provide binding, so return null return null } override fun onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show() } }
Java
public class HelloService extends Service { private Looper serviceLooper; private ServiceHandler serviceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000); } catch (InterruptedException e) { // Restore interrupt status. Thread.currentThread().interrupt(); } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work doesn't disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler serviceLooper = thread.getLooper(); serviceHandler = new ServiceHandler(serviceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = serviceHandler.obtainMessage(); msg.arg1 = startId; serviceHandler.sendMessage(msg); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }
El código de ejemplo controla todas las llamadas entrantes en onStartCommand()
.
y publica el trabajo en un Handler
que se ejecuta en un subproceso en segundo plano. Funciona como una IntentService
y procesa todas las solicitudes en serie, una tras otra.
Puedes cambiar el código para que ejecute el trabajo en un conjunto de subprocesos, por ejemplo, si deseas ejecutar varias solicitudes de forma simultánea.
Ten en cuenta que el método onStartCommand()
debe mostrar un
entero. El número entero es un valor que describe cómo el sistema debe continuar el servicio en la
evento de que el sistema la finaliza. El valor que se muestra
de onStartCommand()
debe ser uno de los siguientes
constantes:
START_NOT_STICKY
- Si el sistema finaliza el servicio después de que devuelve
onStartCommand()
, no vuelvas a crear el servicio, a menos que haya pendientes. que se pueden entregar. Esta es la opción más segura para evitar que se ejecute tu servicio cuando no es necesario y cuando tu aplicación puede simplemente reiniciar los trabajos sin terminar. START_STICKY
- Si el sistema cierra el servicio después de que se muestra
onStartCommand()
, vuelve a crear el servicio y llama aonStartCommand()
, pero no vuelvas a entregar el último intent. En cambio, el sistema llama aonStartCommand()
con un null a menos que haya intents pendientes para iniciar el servicio. En ese caso, se entregan esos intents. Esto es adecuado para reproductores multimedia (o servicios similares) que no que ejecutan comandos, pero que se ejecutan de forma indefinida y esperan un trabajo. START_REDELIVER_INTENT
- Si el sistema finaliza el servicio después de que se muestra
onStartCommand()
, vuelve a crear el servicio y llama aonStartCommand()
con el último intent entregado al servicio. A su vez, se entregarán todas las intents pendientes. Esto es adecuado para los servicios activamente realizando un trabajo que debe reanudarse inmediatamente, como descargar un archivo.
Para obtener más detalles sobre los valores que se devuelven, consulta la referencia vinculada. documentación para cada constante.
Cómo iniciar un servicio
Puedes iniciar un servicio desde una actividad u otro componente de la aplicación
pasar un Intent
a startService()
o startForegroundService()
. El
El sistema Android llama al método onStartCommand()
del servicio y le pasa el Intent
.
que especifica qué servicio iniciar.
Nota: Si tu app está orientada al nivel de API 26 o uno superior, el sistema
impone restricciones sobre el uso o la creación de servicios en segundo plano, a menos que la app
está en primer plano. Si una app necesita crear un servicio en primer plano,
la app debe llamar a startForegroundService()
. Ese método crea un servicio en segundo plano, pero la
indica al sistema que el servicio se promocionará
primer plano. Cuando se crea el servicio, este debe llamar a su
método startForeground()
en
cinco segundos.
Por ejemplo, una actividad puede iniciar el servicio de ejemplo de la sección anterior (HelloService
) mediante un intent explícito con startService()
, como se muestra a continuación:
Kotlin
startService(Intent(this, HelloService::class.java))
Java
startService(new Intent(this, HelloService.class));
El método startService()
se muestra de inmediato.
el sistema Android llama al método onStartCommand()
del servicio. Si aún no se está ejecutando el servicio, el sistema primero llama a onCreate()
y, luego,
onStartCommand()
Si el servicio no proporciona también enlaces, el intent que se entrega con startService()
es el único modo de comunicación entre los
componente de la aplicación y el servicio. Sin embargo, si quieres que el servicio devuelva un resultado,
el cliente que inicia el servicio puede crear un PendingIntent
para una transmisión
(con getBroadcast()
) y entregarlo al servicio
en la Intent
que inicia el servicio. Luego, el servicio puede usar
para entregar un resultado.
Las múltiples solicitudes para iniciar el servicio dan como resultado múltiples llamadas correspondientes a la
onStartCommand()
Sin embargo, solo una solicitud para detener
se necesita el servicio (con stopSelf()
o stopService()
) para detenerlo.
Cómo detener un servicio
Un servicio iniciado debe administrar su propio ciclo de vida. Es decir, el sistema no se detiene ni
destruirá el servicio, a menos que deba recuperar la memoria del sistema y el servicio
sigue ejecutándose después de que se devuelve onStartCommand()
. El
servicio debe detenerse a sí mismo llamando a stopSelf()
, o bien a otro
puede detenerlo llamando a stopService()
.
Una vez que se solicita la detención con stopSelf()
o stopService()
, el sistema destruye el servicio en cuanto
como sea posible.
Si tu servicio controla varias solicitudes a onStartCommand()
de forma simultánea, no debes detener la
cuando hayas terminado de procesar una solicitud de inicio, ya que es posible que
solicitud de inicio (si se detenía al final de la primera solicitud terminaría la segunda). Para evitar
este problema, puedes usar stopSelf(int)
para garantizar que tu solicitud a
detener el servicio siempre se basa en la solicitud de inicio más reciente. Es decir, cuando llamas a stopSelf(int)
, pasas el ID de la solicitud de inicio (el objeto startId
entregado a onStartCommand()
) a la cual tu solicitud de detención
corresponde. Luego, si el servicio recibe una nueva solicitud de inicio antes de que puedas llamar a stopSelf(int)
, el ID no coincidirá y el servicio no se detendrá.
Precaución: Para evitar desperdiciar recursos del sistema y consumir
la batería, asegúrate de que tu aplicación detenga los servicios cuando deje de funcionar.
Si es necesario, otros componentes pueden detener el servicio llamando a stopService()
. Incluso si habilitas la vinculación para el servicio,
Siempre debes detener el servicio por tu cuenta si alguna vez recibe una llamada a onStartCommand()
.
Para obtener más información sobre el ciclo de vida de un servicio, consulta la siguiente sección sobre Cómo administrar el ciclo de vida de un servicio.
Cómo crear un servicio enlazado
Un servicio vinculado es aquel que permite que los componentes de la aplicación se vinculen a él llamando a bindService()
para crear una conexión de larga duración.
Por lo general, no permite que los componentes lo inicien llamando a startService()
.
Crea un servicio vinculado cuando quieras interactuar con el servicio desde actividades y otros componentes de tu aplicación, o para exponer algunas de sus funcionalidades a otras aplicaciones a través de la comunicación entre procesos (IPC).
Para crear un servicio vinculado, implementa el método de devolución de llamada onBind()
para mostrar un IBinder
que
define la interfaz para la comunicación con el servicio. Luego, otros componentes de la aplicación pueden llamar
bindService()
para recuperar la interfaz y
comenzar a llamar a métodos en el servicio. El servicio está activo solo para entregar el componente de la aplicación que
está vinculado al servicio. Por lo tanto, cuando no hay componentes vinculados al servicio, el sistema lo destruye.
No es necesario detener un servicio enlazado de la misma manera que cuando el servicio se
comenzaron hasta onStartCommand()
.
Para crear un servicio de enlace, debes definir la interfaz que especifique cómo un cliente puede
para comunicarse con el servicio. Esta interfaz entre los servicios
y un cliente debe ser una implementación de IBinder
, y es lo que debe hacer tu servicio
que devuelve el método de devolución de llamada onBind()
. Después de que el cliente recibe el IBinder
, puede comenzar
interactuar con el servicio a través de esa interfaz.
Se pueden enlazar varios clientes al servicio a la vez. Cuando un cliente termina de interactuar con
al servicio, llama a unbindService()
para realizar la desvinculación.
Cuando ya no hay clientes enlazados con el servicio, el sistema lo destruye.
Existen varias formas de implementar un servicio vinculado, y la implementación es más complicada que un servicio iniciado. Por estos motivos, el análisis del servicio enlazado aparece en un documento separado sobre los Servicios vinculados.
Enviar notificaciones al usuario
Cuando un servicio se está ejecutando, puede notificar al usuario sobre los eventos mediante notificaciones de la barra de notificaciones o notificaciones de la barra de estado.
Una notificación de la barra de notificaciones es un mensaje que aparece en la superficie de la ventana actual solo un momento antes de desaparecer. Una notificación en la barra de estado muestra un ícono en la barra de estado con un mensaje, que el usuario puede seleccionar para realizar una acción (como iniciar una actividad).
Por lo general, una notificación de la barra de estado es la mejor técnica para usar en segundo plano, como se completó la descarga de un archivo y el usuario ahora puede realizar acciones al respecto. Cuando el usuario selecciona la notificación de la vista expandida, la notificación puede iniciar una actividad (por ejemplo, para mostrar el archivo descargado).
Administrar el ciclo de vida de un servicio
El ciclo de vida de un servicio es mucho más simple que el de una actividad. Sin embargo, es incluso más importante que preste mucha atención a la forma en que se crea y se destruye tu Service puede ejecutarse en segundo plano sin que el usuario esté al tanto.
El ciclo de vida del servicio, desde que se crea hasta que se destruye, puede seguir cualquiera de estas dos rutas:
- Un servicio iniciado
El servicio se crea cuando otro componente llama a
startService()
. El servicio se ejecuta de forma indefinida se detiene llamando astopSelf()
. Otro componente también puede detener la de servicio llamando astopService()
. Una vez que se detiene el servicio, el sistema lo destruye. - Un servicio enlazado
El servicio se crea cuando otro componente (un cliente) llama a
bindService()
. Luego, el cliente se comunica con el servicio a través de una interfazIBinder
. El cliente puede cerrar la conexión llamandounbindService()
Varios clientes pueden vincularse con el mismo servicio y cuando todos ellos se desvinculan, el sistema destruye el servicio. El servicio no necesita detenerse a sí mismo.
Estas dos rutas de acceso no son completamente separadas. Puedes vincularte a un servicio que ya esté
comenzó con startService()
. Por ejemplo, puedes
Inicia un servicio de música en segundo plano llamando a startService()
con un Intent
que identifica la música que se reproducirá. Luego,
posiblemente cuando el usuario quiere ejercer algún control sobre el jugador u obtener información sobre la
canción actual, una actividad puede vincularse al servicio llamando a bindService()
. En casos como este, stopService()
o stopSelf()
no detienen el servicio hasta que se desvinculan todos los clientes.
Implementar devoluciones de llamada del ciclo de vida
Al igual que una actividad, un servicio tiene métodos de devolución de llamada de ciclo de vida que puedes implementar para supervisar cambios en el estado del servicio y realizar trabajos en los momentos adecuados. El siguiente esqueleto servicio muestra cada uno de los métodos del ciclo de vida:
Kotlin
class ExampleService : Service() { private var startMode: Int = 0 // indicates how to behave if the service is killed private var binder: IBinder? = null // interface for clients that bind private var allowRebind: Boolean = false // indicates whether onRebind should be used override funonCreate
() { // The service is being created } override funonStartCommand
(intent: Intent?, flags: Int, startId: Int): Int { // The service is starting, due to a call to startService() return startMode } override funonBind
(intent: Intent): IBinder? { // A client is binding to the service with bindService() return binder } override funonUnbind
(intent: Intent): Boolean { // All clients have unbound with unbindService() return allowRebind } override funonRebind
(intent: Intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } override funonDestroy
() { // The service is no longer used and is being destroyed } }
Java
public class ExampleService extends Service { int startMode; // indicates how to behave if the service is killed IBinder binder; // interface for clients that bind boolean allowRebind; // indicates whether onRebind should be used @Override public voidonCreate
() { // The service is being created } @Override public intonStartCommand
(Intent intent, int flags, int startId) { // The service is starting, due to a call tostartService()
return startMode; } @Override public IBinderonBind
(Intent intent) { // A client is binding to the service withbindService()
return binder; } @Override public booleanonUnbind
(Intent intent) { // All clients have unbound withunbindService()
return allowRebind; } @Override public voidonRebind
(Intent intent) { // A client is binding to the service withbindService()
, // after onUnbind() has already been called } @Override public voidonDestroy
() { // The service is no longer used and is being destroyed } }
Nota: A diferencia de los métodos de devolución de llamada del ciclo de vida de la actividad, no es necesario llamar a la implementación de la superclase de estos métodos de devolución de llamada.
En la figura 2, se ven los métodos de devolución de llamada habituales de un servicio. Aunque la figura separa
servicios que creó startService()
a partir de esos
creado por bindService()
, mantener
Recuerda que cualquier servicio, sin importar cómo se inicie, puede permitir que los clientes se vinculen con él.
Un servicio que se inició en un principio con onStartCommand()
(por un cliente que llama a startService()
)
aún puede recibir una llamada a onBind()
(cuando un cliente llama
bindService()
).
Al implementar estos métodos, puedes supervisar estos dos bucles anidados de la capa de recursos ciclo de vida:
- El ciclo de vida completo de un servicio ocurre entre el momento en el que se llama a
onCreate()
y el momento en el que se muestraonDestroy()
. Al igual que una actividad, un servicio realiza su configuración inicial deonCreate()
y libera todos los recursos restantes enonDestroy()
. Por ejemplo, un El servicio de reproducción de música puede crear el subproceso en el que se reproduce la música enonCreate()
y, luego, detenerlo enonDestroy()
.Nota: El elemento
onCreate()
yonDestroy()
para todos los servicios, ya sea son creadas porstartService()
obindService()
. - La ciclo de vida activa de un servicio comienza con una llamada a
onStartCommand()
oonBind()
. A cada método se le entrega laIntent
que se pasó astartService()
obindService()
.Si se inicia el servicio, el ciclo de vida activo finaliza al mismo tiempo que finaliza (el servicio sigue activo incluso después de que se devuelve
onStartCommand()
). Si el servicio está vinculado, el ciclo de vida activo finaliza cuando se devuelveonUnbind()
.
Nota: Si bien un servicio iniciado se detiene con una llamada a
stopSelf()
o stopService()
, no hay una devolución de llamada respectiva para el
(no hay devolución de llamada onStop()
). A menos que el servicio esté vinculado a un cliente,
el sistema la destruye cuando se detiene el servicio (onDestroy()
es la única devolución de llamada recibida).
Para obtener más información sobre cómo crear un servicio que proporciona vinculación, consulta el documento Servicios vinculados.
en la que se incluye más información sobre onRebind()
método de devolución de llamada en la sección Cómo administrar el ciclo de vida de
un servicio vinculado.