Skip to content

Most visited

Recently visited

navigation

Servicios

Un Service es un componente de una aplicación que puede realizar operaciones de larga ejecución en segundo plano y que no proporciona una interfaz de usuario. Otro componente de la aplicación puede iniciar un servicio y continuará ejecutándose en segundo plano aunque el usuario cambie a otra aplicación. Además, un componente puede enlazarse con un servicio para interactuar con él e incluso realizar una comunicación entre procesos (IPC). Por ejemplo, un servicio puede manejar transacciones de red, reproducir música, realizar I/O de archivos o interactuar con un proveedor de contenido, todo en segundo plano.

Un servicio puede adoptar esencialmente dos formas:

Servicio iniciado
Un servicio está "iniciado" cuando un componente de aplicación (como una actividad) lo inicia llamando a startService(). Una vez iniciado, un servicio puede ejecutarse en segundo plano de manera indefinida, incluso si se destruye el componente que lo inició. Por lo general, un servicio iniciado realiza una sola operación y no devuelve un resultado al emisor. Por ejemplo, puede descargar o cargar un archivo a través de la red. Cuando la operación está terminada, el servicio debe detenerse por sí mismo.
Servicio de enlace
Un servicio es de “de enlace” cuando un componente de la aplicación se vincula a él llamando a bindService(). Un servicio de enlace ofrece una interfaz cliente-servidor que permite que los componentes interactúen con el servicio, envíen solicitudes, obtengan resultados e incluso lo hagan en distintos procesos con la comunicación entre procesos (IPC). Un servicio de enlace se ejecuta solamente mientras otro componente de aplicación está enlazado con él. Se pueden enlazar varios componentes con el servicio a la vez, pero cuando todos ellos se desenlazan, el servicio se destruye.

En esta documentación, estos tipos de servicios generalmente se abordan por separado, pero el tuyo puede funcionar de ambas formas; puede iniciarse (para ejecutarse de manera indefinida) y también permitir los enlaces. Solo depende de que implementes un par de métodos de callback: onStartCommand() para permitir que los componentes lo inicien, y onBind() para permitir los enlaces.

Independientemente de que tu aplicación esté iniciada, enlazada o ambas, cualquier componente de la aplicación puede utilizar el servicio (incluso desde otra aplicación), de la misma forma que cualquier componente puede utilizar una actividad—iniciándola con una Intent. Sin embargo, tú puedes declarar el servicio como privado, en el archivo de manifiesto, y bloquear el acceso de otras aplicaciones. Esto se explica en más detalle en la sección Declaración del servicio en el manifiesto.

Advertencia: Un servicio se ejecuta en el subproceso principal de su proceso de alojamiento; el servicio no crea su propio subproceso y no se ejecuta en un proceso separado (salvo que usted especifique lo contrario). Esto significa que, si tu servicio va a realizar un trabajo que consume más CPU u operaciones de bloqueo (como reproducción MP3 o funciones de red), debes crear un subproceso nuevo dentro del servicio para realizar ese trabajo. Al utilizar un subproceso independiente, reducirás el riesgo de que se produzcan errores de tipo "La aplicación no responde (ANR)", y el subproceso principal de la aplicación puede continuar dedicado a la interacción del usuario con tus actividades.

Conceptos básicos

Para crear un servicio, debes crear una subclase de Service (o una de sus subclases existentes). En tu implementación, debes reemplazar algunos métodos callback que manejan aspectos fundamentales del ciclo de vida del servicio y proporcionar un mecanismo para que los componentes se enlacen con el servicio, si corresponde. Los métodos callback más importantes que debes reemplazar son los siguientes:

onStartCommand()
El sistema llama a este método cuando otro componente, como una actividad, solicita que se inicie el servicio, llamando a startService(). Una vez que se ejecuta este método, el servicio se inicia y se puede ejecutar en segundo plano de manera indefinida. Si implementas esto, será tu responsabilidad detener el servicio cuando tu trabajo esté terminado. Para ello, llama a stopSelf() o stopService(). (Si solo deseas proporcionar enlaces, no necesitas implementar este método).
onBind()
El sistema llama a este método cuando otro componente desea enlazarse con el servicio (por ejemplo, para ejecutar RPC), llamando a bindService(). En tu implementación de este método, debes proporcionar una interfaz que los clientes utilicen para comunicarse con el servicio, devolviendo una IBinder. Siempre debes implementar este método, pero si no deseas permitir los enlaces, debes devolver NULL.
onCreate()
El sistema llama a este método cuando se crea el servicio por primera vez, para realizar los procedimientos de configuración por única vez (antes de llamar a onStartCommand() o onBind()). Si el servicio ya se está ejecutando, no se llama a este método.
onDestroy()
El sistema llama a este método cuando el servicio ya no se utiliza y se lo está destruyendo. Tu servicio debe implementar esto para limpiar recursos como subprocesos, escuchas (listeners) registrados, receptores, etc. 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 hasta que otro componente lo detiene llamando a stopService().

Si un componente llama a bindService() para crear el servicio (y no se llama aonStartCommand()), el servicio se ejecuta solamente si el componente está enlazado con él. Una vez que el servicio se desenlaza de todos los clientes, el sistema lo destruye.

El sistema Android forzará la detención de un servicio solo cuando hay poca memoria y debe recuperar los recursos del sistema para la actividad que tiene el foco del usuario. Si el servicio está enlazado con una actividad que tiene el foco del usuario, es menos probable que se lo cierre, y si el servicio está declarado para ejecutarse en primer plano (lo que se explica a continuación), casi nunca se lo cerrará. De lo contrario, si el servicio es iniciado y de larga ejecución, con el tiempo el sistema lo colocará en una posición más baja en la lista de tareas en segundo plano, y el servicio pasará a ser muy susceptible al cierre; si su servicio es iniciado, debe diseñarlo de modo tal que maneje correctamente los reinicios efectuados por el sistema. Si el sistema cierra su servicio, lo reinicia apenas los recursos vuelven a estar disponibles (aunque esto también depende del valor que muestres desde onStartCommand(), como se explica más adelante). Para obtener más información sobre los casos en los que el sistema puede destruir un servicio, consulta el documento Procesos y subprocesos .

En las secciones siguientes, verás cómo puedes crear cada tipo de servicio y cómo utilizarlo desde componentes de otras aplicaciones.

Declaración de un servicio en el manifiesto

Al igual que las actividades (y otros componentes), debes declarar todos los servicios en el archivo de manifiesto de tu aplicación.

Para declarar tu servicio, agrega un elemento <service> como campo secundario del elemento de <application> . Por ejemplo:

<manifest ... >
  ...
  <application ... >
      <service android:name=".ExampleService" />
      ...
  </application>
</manifest>

Consulta la referencia del elemento <service> para obtener más información sobre la manera de declarar tu servicio en el manifiesto.

Existen otros atributos que puedes incluir en el elemento <service> a fin de definir propiedades tales como los permisos necesarios para iniciar el servicio y el proceso en el cual se debe ejecutar el servicio. El atributo android:name es el único atributo obligatorio y especifica el nombre de clase del servicio. Una vez que publicas tu aplicación, no debes cambiar este nombre ya que, si lo haces, se arriesga a interrumpir el código debido a la dependencia de intents explícitas de iniciar o enlazar el servicio (lee la publicación del blog Cosas que no pueden cambiar).

Para garantizar que tu aplicación sea segura, utiliza siempre una intent explícita cuando inicia o enlaza su Service y no declares filtros de intents para el servicio. Si es fundamental que permitas una cierta ambigüedad en cuanto al servicio que se inicia, puedes proporcionar filtros de intents para tus servicios y excluir el nombre del componente de Intent. Sin embargo, en ese caso debes configurar el paquete para la intent con setPackage(), que proporciona suficiente desambiguación para el servicio de destino.

Además, puedes garantizar que tu servicio esté disponible solo para tu app incluyendo el atributo android:exported y fijándolo en "false". Esto impide que otras aplicaciones inicien tu servicio, incluso cuando se utiliza una intent explícita.

Creación de un servicio iniciado

Un servicio iniciado es un servicio que otro componente inicia llamando a startService(), lo cual da como resultado una llamada al método onStartCommand() del servicio.

Cuando un servicio es iniciado, tiene un ciclo de vida que es independiente del componente que lo inició, y el servicio puede ejecutarse en segundo plano de manera indefinida, incluso si se destruye el componente que lo inició. Por ende, el servicio debe detenerse a sí mismo cuando su trabajo está terminado llamando a stopSelf(), o bien, otro componente puede detenerlo llamando a stopService().

Un componente de una aplicación, como una actividad, puede iniciar el servicio llamando a startService() y pasando una Intent que especifique el servicio e incluya datos para el servicio. El servicio recibe esta Intent en el método onStartCommand().

Por ejemplo, supón que una actividad necesita guardar datos en una base de datos en línea. La actividad puede iniciar un servicio complementario y enviar a este los datos que se guardarán pasando una intent a startService(). El servicio recibe la intent en onStartCommand(), se conecta a Internet y realiza la transacción de la base de datos. Cuando la transacción está terminada, el servicio se detiene a sí mismo y se lo destruye.

Advertencia: Un servicio se ejecuta en el mismo proceso que la aplicación en la cual está declarado y en el subproceso principal de esta, de forma predeterminada. Por lo tanto, si tu servicio realiza operaciones intensivas o de bloqueo mientras el usuario interactúa con una actividad desde la misma aplicación, el servicio retardará el rendimiento de la actividad. Para evitar el impacto en el rendimiento de la aplicación, debes iniciar un subproceso nuevo dentro del servicio.

Tradicionalmente, existen dos clases que puedes extender para crear un servicio iniciado:

Service
Esta es la clase base para todos los servicios. Cuando extiendes esta clase, es importante que crees un subproceso nuevo, en el cual se realizarán todo el trabajo del servicio, porque el servicio utiliza el subproceso principal de tu aplicación de forma predeterminada, lo que podría ralentizar el rendimiento de cualquier actividad que tu aplicación esté ejecutando.
IntentService
Esta es una subclase de Service que utiliza un subproceso de trabajo para manejar todas las solicitudes de inicio, una a la vez. Esta es la mejor opción si no necesitas que tu servicio maneje múltiples solicitudes simultáneamente. Lo único que debes hacer es implementar onHandleIntent(), que recibe la intent de cada solicitud de inicio para que puedas realizar el trabajo en segundo plano.

En las secciones siguientes, se describe cómo puedes implementar tu servicio utilizando cualquiera de estas clases.

Extensión de la clase IntentService

Dado que la mayoría de los servicios iniciados no necesita manejar múltiples solicitudes simultáneamente (lo que, en realidad, puede ser un escenario peligroso de subprocesos múltiples), probablemente sea mejor si implementas tu servicio utilizando la clase IntentService.

La IntentService realiza lo siguiente:

En síntesis, lo único que debes hacer es implementar onHandleIntent() para hacer el trabajo proporcionado por el cliente. (sin embargo, también debes proporcionar un pequeño constructor para el servicio).

A continuación, se incluye un ejemplo de implementación de IntentService:

public class HelloIntentService extends IntentService {

  /**
   * A constructor is required, and must call the super IntentService(String)
   * constructor with a name for the worker thread.
   */
  public HelloIntentService() {
      super("HelloIntentService");
  }

  /**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */
  @Override
  protected void onHandleIntent(Intent intent) {
      // 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();
      }
  }
}

Eso es todo lo que necesitas: un constructor y una implementación de onHandleIntent().

Si decides reemplazar también otros métodos de callback, como onCreate(), onStartCommand() o onDestroy(), asegúrate de llamar a la superimplementación, para que el IntentService pueda manejar correctamente el ciclo de vida del subproceso de trabajo.

Por ejemplo, onStartCommand() debe mostrar la implementación predeterminada (que es la forma en la que se entrega la intent a onHandleIntent()):

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
    return super.onStartCommand(intent,flags,startId);
}

Además de onHandleIntent(), el único método del cual no necesitas llamar a la superclase es onBind() (pero solo debes implementarlo si tu servicio permite los enlaces).

En la sección siguiente, verás cómo la misma clase de servicio se implementa al extender la clase base Service, lo cual es mucho más código, pero puede ser adecuado si necesitas manejar solicitudes de inicio simultáneas.

Extensión de la clase Service

Como viste en la sección anterior, el uso de IntentService hace que la implementación de un servicio iniciado sea muy simple. Sin embargo, si necesitas que tu servicio realice varios subprocesos (en lugar de procesar las solicitudes de inicio a través de una cola de trabajo), puedes extender la clase Service para manejar cada intento.

Para fines comparativos, el código de ejemplo siguiente es una implementación de la clase Service que realiza exactamente el mismo trabajo que el ejemplo anterior usando IntentService. Es decir, para cada solicitud de inicio, utiliza un subproceso de trabajo para realizar el trabajo y procesa solo una solicitud a la vez.

public class HelloService extends Service {
  private Looper mServiceLooper;
  private ServiceHandler mServiceHandler;

  // 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 will not 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
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
  }

  @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 = mServiceHandler.obtainMessage();
      msg.arg1 = startId;
      mServiceHandler.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();
  }
}

Como puedes ver, es mucho más trabajo que utilizar IntentService.

Sin embargo, como tú mismo manejas cada llamada a onStartCommand(), puedes realizar múltiples solicitudes simultáneamente. Esto no es lo que hace este ejemplo, pero si es lo que deseas, puedes crear un subproceso nuevo para cada solicitud y ejecutarlas de inmediato (en lugar de esperar a que finalice la solicitud anterior).

Ten en cuenta que el método onStartCommand() debe devolver un entero. El valor entero es un valor que describe la forma en que el sistema debe continuar el servicio en caso de que el sistema lo cierre (como se explicó anteriormente, la implementación predeterminada de IntentService se encarga de esto, aunque puedes modificarlo). El valor de retorno de onStartCommand() debe ser una de las siguientes constantes:

START_NOT_STICKY
Si el sistema cierra el servicio después de que se devuelve onStartCommand(), no vuelve a crear el servicio, salvo que existan intents pendientes para entregar. Esta es la opción más segura para evitar que tu servicio se ejecute cuando no es necesario y cuando tu aplicación puede simplemente reiniciar los trabajos no finalizados.
START_STICKY
Si el sistema cierra el servicio después de que se muestre onStartCommand(), vuelve a crear el servicio y llama al onStartCommand(), pero no vuelvas a entregar la última intent. Como alternativa, el sistema llama a onStartCommand() con una intent nula, a menos que existan intents pendientes para iniciar el servicio, en cuyo caso se entregarán estas últimas. Esto es adecuado para reproductores multimedia (o servicios similares) que no ejecutan comandos, sino que se ejecutan de forma indefinida y esperan un trabajo.
START_REDELIVER_INTENT
Si el sistema cierra el servicio después de que se devuelve onStartCommand(), vuelve a crear el servicio y llama a onStartCommand() con la última intent que se entregó al servicio. A su vez, se entregan todas las intents pendientes. Esto es adecuado para servicios que ejecutan activamente un trabajo y deben reanudarse inmediatamente, por ejemplo, descargar un archivo.

Para obtener más detalles sobre estos valores de retorno, consulta la documentación de referencia vinculada de cada constante.

Inicio de un servicio

Puedes iniciar un servicio desde una actividad u otro componente de la aplicación pasando un Intent (especifica que el servicio se inicie) a startService(). El sistema de Android llama al método del servicio onStartCommand() y le pasa la Intent. (Nunca debes llamar a onStartCommand() directamente).

Por ejemplo, una actividad puede iniciar el servicio del ejemplo de la sección anterior (HelloService) usando una intent explícita con startService():

Intent intent = new Intent(this, HelloService.class);
startService(intent);

Se devuelve inmediatamente el método startService() y el sistema Android llama al método del servicio onStartCommand(). Si el servicio aún no está en ejecución, el sistema llama primero a onCreate() y luego llama a onStartCommand().

Si el servicio no proporciona también enlaces, la intent entregada con startService() es el único elemento de comunicación entre el componente de la aplicación y el servicio. Sin embargo, si deseas que el servicio devuelva un resultado, el cliente que inicia el servicio puede crear una PendingIntent para un mensaje (con getBroadcast()) y entregarla al servicio en la Intent que inicia el servicio. Luego, el servicio puede utilizar el mensaje para entregar un resultado.

Las múltiples solicitudes para iniciar el servicio dan como resultado múltiples llamadas correspondientes al onStartCommand()del servicio. Sin embargo, solo se necesita una solicitud de detención del servicio (con stopSelf() o stopService()) para detenerlo.

Detención de un servicio

Un servicio iniciado debe administrar su propio ciclo de vida. Es decir, el sistema no detiene ni destruye el servicio salvo que deba recuperar memoria del sistema, y el servicio continúa ejecutándose después de que se devuelve onStartCommand(). Por lo tanto, el servicio debe detenerse a sí mismo llamando a stopSelf(), o bien, otro componente puede detenerlo llamando a stopService().

Una vez que se solicita la detención con stopSelf() o stopService(), el sistema destruye el servicio lo más pronto posible.

Sin embargo, si tu servicio maneja varias solicitudes a onStartCommand() simultáneamente, no debes detener el servicio cuando termine de procesar una solicitud de inicio, ya que probablemente hayas recibido una nueva solicitud (la detención al final de la primera solicitud interrumpiría la segunda solicitud). Para evitar este problema, puedes utilizar stopSelf(int) para garantizar que tu solicitud de detener el servicio se base siempre en la solicitud de inicio más reciente. Es decir, cuando llamas a stopSelf(int), pasas el ID de la solicitud de inicio (el startId entregado a onStartCommand()) al cual corresponde tu solicitud de detención. 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á.

Advertencia: Es importante que tu aplicación detenga los servicios cuando ha terminado de trabajar, a fin de evitar que se desperdicien recursos del sistema y se consuma la carga de la batería. Si es necesario, otros componentes pueden detener el servicio llamando a stopService(). Aun cuando habilites los enlaces para el servicio, siempre debes detener el servicio tú mismo si alguna vez recibe una llamada a onStartCommand().

Para obtener más información sobre el ciclo de vida de un servicio, consulta la sección Administración del ciclo de vida de un servicio que aparece más adelante.

Creación de un servicio enlazado

Un servicio de enlace es un servicio que permite que los componentes de la aplicación se enlacen con él llamando a bindService() para crear una conexión a largo plazo (y generalmente no permite que los componentes lo inicien llamando a startService()).

Debes crear un servicio de enlace cuando deseas interactuar con el servicio desde las actividades y otros componentes de tu aplicación, o exponer algunas de las funciones de tu aplicación a otras aplicaciones, a través de la comunicación entre procesos (IPC).

Para crear un servicio de enlace, debes implementar el método de callback onBind() a fin de devolver un IBinder que defina la interfaz para la comunicación con el servicio. Luego, otros componentes de la aplicación pueden llamar a bindService() para recuperar la interfaz y comenzar a llamar métodos en el servicio. El servicio solo está activo para servir al componente de la aplicación que está enlazado con él; por lo tanto, cuando no hay componentes enlazados con el servicio, el sistema lo destruye (no es necesario que detengas un servicio de enlace de la forma en la que debes hacerlo cuando el servicio se inicia a través de onStartCommand()).

Para crear un servicio de enlace, lo primero que debes hacer es definir la interfaz que especifica cómo un cliente puede comunicarse con el servicio. Esta interfaz entre el servicio y un cliente debe ser una implementación de IBinder y es lo que tu servicio debe devolver desde el método callback onBind(). Una vez que el cliente recibe el IBinder, puede comenzar a interactuar con el servicio a través de esa interfaz.

Se pueden enlazar varios clientes con el servicio a la vez. Cuando un cliente termina de interactuar con el servicio, llama a unbindService() para desenlazarse. Una vez que no hay clientes enlazados con el servicio, el sistema destruye el servicio.

Existen varias formas de implementar un servicio de enlace, y la implementación es más complicada que la de un servicio iniciado; por lo tanto, la explicación sobre los servicios de enlace aparece en un documento separado sobre Servicios de enlace.

Envío de notificaciones al usuario

Una vez que se está ejecutando, un servicio puede notificar al usuario acerca de los eventos utilizando notificaciones del sistema o notificaciones de la barra de estado.

Una notificación del sistema es un mensaje que aparece en la superficie de la ventana actual durante un momento y luego desaparece, mientras que una notificación de la barra de estado proporciona un ícono en la barra de estado con un mensaje, que el usuario puede seleccionar para realizar una acción (por ejemplo, iniciar una actividad).

Por lo general, una notificación de la barra de estado es la mejor técnica cuando se ha completado un trabajo en segundo plano (por ejemplo, se completó la descarga de un archivo) y el usuario ya puede utilizarlo. Cuando el usuario selecciona la notificación desde la vista expandida, la notificación puede iniciar una actividad (por ejemplo, ver el archivo descargado).

Consulta las guías para desarrolladores Notificaciones del sistema o Notificaciones de la barra de estado para obtener más información.

Ejecución de un servicio en primer plano

Un servicio en primer plano es un servicio que se considera como algo de lo que el usuario está activamente consciente y, por ende, no es candidato a que el sistema lo cierre cuando tiene poca memoria. Un servicio en primer plano debe proporcionar una notificación para la barra de estado, que se encuentra debajo del encabezado “En curso”, lo que significa que la notificación no se puede descartar, salvo que el servicio se detenga o se quite del primer plano.

Por ejemplo, un reproductor de música que reproduce música desde un servicio se debe configurar para que se ejecute en primer plano, porque el usuario está explícitamente al tanto de su operación. La notificación en la barra de estado puede indicar la canción actual y permitir que el usuario lance una actividad para interactuar con el reproductor de música.

Para solicitar que tu servicio se ejecute en primer plano, llama a startForeground(). Este método tiene dos parámetros: un valor entero que identifica de forma exclusiva la notificación y la Notification para la barra de estado. Por ejemplo:

Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
        System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
        getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

Advertencia: El ID del valor entero que asignas a startForeground() no debe ser 0.

Para quitar el servicio del primer plano, llama al stopForeground(). Este método tiene un valor booleano, que indica si también se debe quitar la notificación de la barra de estado. Este método no detiene el servicio. Sin embargo, si detienes el servicio mientras aún se está ejecutando en primer plano, también se quita la notificación.

Para obtener más información sobre las notificaciones, consulta la sección Creación de notificaciones de la barra de estado.

Administración del 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 aún más importante que prestes mucha atención a la forma en la que se crea y se destruye tu servicio, porque un servicio se puede ejecutar en segundo plano sin que el usuario esté al tanto.

El ciclo de vida del servicio (desde el momento en que se crea hasta que se destruye) puede seguir dos rutas de acceso diferentes:

Estas dos rutas de acceso no son completamente independientes. Es decir, tú puedes establecer un enlace con un servicio que ya se inició con startService(). Por ejemplo, un servicio de música en segundo plano puede iniciarse llamando a startService() con una Intent que identifica la música que se ha de reproducir. Luego, posiblemente cuando el usuario desee controlar el reproductor u obtener información sobre la canción actual, una actividad podrá enlazarse con el servicio llamando a bindService(). En casos como este, stopService() o stopSelf() no detiene el servicio hasta que se desvinculen todos los clientes.

Implementación de callbacks del ciclo de vida

Al igual que una actividad, un servicio tiene métodos callback del ciclo de vida que tú puedes implementar para controlar los cambios en el estado del servicio y realizar trabajos en los momentos adecuados. El siguiente servicio estructural demuestra cada uno de los métodos del ciclo de vida:

public class ExampleService extends Service {
    int mStartMode;       // indicates how to behave if the service is killed
    IBinder mBinder;      // interface for clients that bind
    boolean mAllowRebind; // indicates whether onRebind should be used

    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return mAllowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

Nota: A diferencia de los métodos callback del ciclo de vida de una actividad, tú no debes llamar a la implementación de la superclase de estos métodos callback.

Figura 2: Ciclo de vida del servicio. El diagrama de la izquierda muestra el ciclo de vida cuando el servicio se crea con startService(), y el diagrama de la derecha muestra el ciclo de vida cuando el servicio se crea con bindService().

Al implementar estos métodos, puedes controlar dos bucles anidados del ciclo de vida del servicio:

Nota: Si bien un servicio iniciado se detiene mediante una llamada a stopSelf() o stopService(), no hay un callback respectivo para el servicio (no hay callback de onStop()). Por lo tanto, a menos que el servicio esté enlazado con un cliente, el sistema lo destruirá cuando el servicio se detenga;onDestroy() es el único callback recibido.

La figura 2 ilustra los métodos callback habituales para un servicio. Si bien en la figura se separan los servicios que se crean mediante startService() de los que se crean mediante bindService(), recuerda que cualquier servicio, no importa cómo se inicie, puede potencialmente permitir que se enlacen clientes con él. Por lo tanto, un servicio que inicialmente se inició con onStartCommand() (por un cliente que llamó a startService()) puede recibir una llamada a onBind() (cuando un cliente llama a bindService()).

Para obtener más información sobre la creación de un servicio que proporciona enlaces, consulta el documento Servicios de enlace, que incluye más información sobre el método callback onRebind() en la sección Administración del ciclo de vida de un servicio de enlace.

This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.