Crear un servicio

Los servicios de Xamarin.Android deben cumplir dos reglas inviolables de los servicios de Android:

Otro requisito de los servicios de Android es que se deben registrar en AndroidManifest.xml y tener un nombre único. Xamarin.Android registrará automáticamente el servicio en el manifiesto en el tiempo de compilación con el atributo XML necesario.

Este fragmento de código es el ejemplo más sencillo de creación de un servicio en Xamarin.Android que cumple estos dos requisitos:

[Service]
public class DemoService : Service
{
    // Magical code that makes the service do wonderful things.
}

En tiempo de compilación, Xamarin.Android registrará el servicio insertando el siguiente elemento XML en AndroidManifest.xml (observe que Xamarin.Android generó un nombre aleatorio para el servicio):

<service android:name="md5a0cbbf8da641ae5a4c781aaf35e00a86.DemoService" />

Es posible compartir un servicio con otras aplicaciones Android mediante su exportación. Esto se consigue estableciendo la propiedad Exported en ServiceAttribute. Al exportar un servicio, la propiedad ServiceAttribute.Name también debería establecerse para proporcionar un nombre público significativo para el servicio. Este fragmento de código muestra cómo exportar y dar nombre a un servicio:

[Service(Exported=true, Name="com.xamarin.example.DemoService")]
public class DemoService : Service
{
    // Magical code that makes the service do wonderful things.
}

El elemento AndroidManifest.xml para este servicio tendrá un aspecto parecido a:

<service android:exported="true" android:name="com.xamarin.example.DemoService" />

Los servicios tienen su propio ciclo de vida con métodos de devolución de llamada que se invocan a medida que se crea el servicio. Los métodos exactos que se invocan dependen del tipo de servicio. Un servicio iniciado debe implementar métodos de ciclo de vida diferentes a los de un servicio enlazado, mientras que un servicio híbrido debe implementar los métodos de devolución de llamada para un servicio iniciado y un servicio enlazado. Todos estos métodos son miembros de la clase Service; la forma en que se inicie el servicio determinará qué métodos del ciclo de vida se invocarán. Estos métodos de ciclo de vida se tratarán con más detalle más adelante.

De forma predeterminada, un servicio se iniciará en el mismo proceso que una aplicación Android. Es posible iniciar un servicio en su propio proceso estableciendo la propiedad ServiceAttribute.IsolatedProcess en true:

[Service(IsolatedProcess=true)]
public class DemoService : Service
{
    // Magical code that makes the service do wonderful things, in it's own process!
}

El siguiente paso consiste en examinar cómo iniciar un servicio y, a continuación, pasar a examinar cómo implementar los tres tipos diferentes de servicios.

Nota:

Un servicio se ejecuta en el subproceso de interfaz de usuario, por lo que si se va a realizar algún trabajo que bloquee la interfaz de usuario, el servicio debe usar subprocesos para realizar el trabajo.

Inicio de un servicio

La manera más básica de iniciar un servicio en Android es enviar un Intent que contiene metadatos para ayudar a identificar qué servicio se debe iniciar. Hay dos estilos diferentes de intenciones que se pueden usar para iniciar un servicio:

  • Intención explícita: una intención explícita identificará exactamente qué servicio se debe usar para completar una acción determinada. Una intención explícita puede considerarse como una carta que tiene una dirección específica; Android dirigirá la intención al servicio que se identifique explícitamente. Este fragmento de código es un ejemplo del uso de una intención explícita para iniciar un servicio denominado DownloadService:

    // Example of creating an explicit Intent in an Android Activity
    Intent downloadIntent = new Intent(this, typeof(DownloadService));
    downloadIntent.data = Uri.Parse(fileToDownload);
    
  • Intención implícita: este tipo de intención identifica de forma flexible el tipo de acción que el usuario desea realizar, pero el servicio exacto para completar esa acción es desconocido. Una intención implícita puede considerarse como una carta que se dirige "A quien corresponda...". Android examinará el contenido de la intención y determinará si hay un servicio existente que coincida con la intención.

    Se usa un filtro de intención para ayudar a hacer coincidir la intención implícita con un servicio registrado. Un filtro de intención es un elemento XML que se agrega a AndroidManifest.xml que contiene los metadatos necesarios para ayudar a hacer coincidir un servicio con una intención implícita.

    Intent sendIntent = new Intent("common.xamarin.DemoService");
    sendIntent.Data = Uri.Parse(fileToDownload);
    

Si Android tiene más de una posible coincidencia para una intención implícita, puede pedir al usuario que seleccione el componente para controlar la acción:

Screenshot of a disambiguation dialog

Importante

A partir de Android 5.0 (nivel 21 de AP), no se puede usar una intención implícita para iniciar un servicio.

Siempre que sea posible, las aplicaciones deben usar intenciones explícitas para iniciar un servicio. Una intención implícita no solicita que se inicie un servicio específico: es una solicitud de algún servicio instalado en el dispositivo para controlar la solicitud. Esta solicitud ambigua puede dar lugar a un servicio incorrecto que controle la solicitud u otra aplicación que se inicie sin necesidad (lo que aumenta la presión de los recursos en el dispositivo).

La forma en que se envía la intención depende del tipo de servicio y se analizará con más detalle más adelante en las guías específicas de cada tipo de servicio.

Creación de un filtro de intención para intenciones implícitas

Para asociar un servicio a una intención implícita, una aplicación Android debe proporcionar algunos metadatos para identificar las funcionalidades del servicio. Estos metadatos los proporcionan los filtros de intención. Los filtros de intención contienen información, como una acción o un tipo de datos, que debe estar presente en una intención para iniciar un servicio. En Xamarin.Android, el filtro de intención se registra en AndroidManifest.xml decorando un servicio con IntentFilterAttribute. Por ejemplo, el código siguiente agrega un filtro de intención con una acción asociada de com.xamarin.DemoService:

[Service]
[IntentFilter(new String[]{"com.xamarin.DemoService"})]
public class DemoService : Service
{
}

Esto da como resultado que una entrada se incluya en el archivo AndroidManifest.xml: una entrada que se empaqueta con la aplicación de una manera análoga al ejemplo siguiente:

<service android:name="demoservice.DemoService">
    <intent-filter>
        <action android:name="com.xamarin.DemoService" />
    </intent-filter>
</service>

Una vez conocidos los conceptos básicos de un servicio de Xamarin.Android, examinemos los distintos subtipos de servicios con más detalle.