Creación de servicios de Android

En esta guía se describen los servicios de Xamarin.Android, que son componentes de Android que permiten realizar el trabajo sin una interfaz de usuario activa. Los servicios se suelen usar para tareas que se realizan en segundo plano, como cálculos lentos, descargando archivos, reproduciendo música, etc. Explica los diferentes escenarios para los que los servicios son adecuados y muestra cómo implementarlos para realizar tareas en segundo plano de larga duración, así como para proporcionar una interfaz para las llamadas a procedimientos remotos.

Introducción a Android Services

Las aplicaciones móviles no son como aplicaciones de escritorio. Los equipos de escritorio tienen grandes cantidades de recursos, como la superficie de pantalla, la memoria, el espacio de almacenamiento y una fuente de alimentación conectada, los dispositivos móviles no. Estas restricciones obligan a las aplicaciones móviles a comportarse de forma diferente. Por ejemplo, la pantalla pequeña de un dispositivo móvil normalmente significa que solo una aplicación (es decir, Actividad) está visible a la vez. Otras actividades se mueven al fondo y se insertan en un estado suspendido donde no pueden realizar ningún trabajo. Sin embargo, solo porque una aplicación Android está en segundo plano no significa que sea imposible que la aplicación siga funcionando.

Las aplicaciones Android se componen de al menos uno de los cuatro componentes principales siguientes: Actividades, Receptores de difusión, Proveedores de contenido y Servicios. Las actividades son la piedra angular de muchas aplicaciones Android excelentes porque proporcionan la interfaz de usuario que permite a un usuario interactuar con la aplicación. Sin embargo, cuando se trata de realizar trabajos simultáneos o en segundo plano, las actividades no siempre son la mejor opción.

El mecanismo principal para el trabajo en segundo plano en Android es el servicio. Un servicio Android es un componente diseñado para realizar algún trabajo sin una interfaz de usuario. Un servicio puede descargar un archivo, reproducir música o aplicar un filtro a una imagen. Los servicios también se pueden usar para la comunicación entre procesos (IPC) entre aplicaciones Android. Por ejemplo, una aplicación Android podría usar el servicio reproductor de música que procede de otra aplicación o una aplicación podría exponer datos (como la información de contacto de una persona) a otras aplicaciones a través de un servicio.

Los servicios y su capacidad de realizar un trabajo en segundo plano son fundamentales para proporcionar una interfaz de usuario fluida y fluida. Todas las aplicaciones android tienen un subproceso principal (también conocido como subproceso de interfaz de usuario) en el que se ejecutan las actividades. Para mantener la capacidad de respuesta del dispositivo, Android debe poder actualizar la interfaz de usuario a la velocidad de 60 fotogramas por segundo. Si una aplicación de Android realiza demasiado trabajo en el subproceso principal, Android quitará fotogramas, lo que a su vez hace que la interfaz de usuario aparezca jerky (también denominada a veces janky). Esto significa que cualquier trabajo realizado en el subproceso de interfaz de usuario debe completarse en el intervalo de tiempo entre dos fotogramas, aproximadamente 16 milisegundos (1 segundo cada 60 fotogramas).

Para solucionar este problema, un desarrollador puede usar subprocesos en una actividad para realizar algún trabajo que bloquee la interfaz de usuario. Sin embargo, esto podría causar problemas. Es muy posible que Android destruya y vuelva a crear las varias instancias de la actividad. Sin embargo, Android no destruirá automáticamente los subprocesos, lo que podría dar lugar a pérdidas de memoria. Un ejemplo primo de esto es cuando se gira el dispositivo : Android intentará destruir la instancia de la actividad y, a continuación, volver a crear una nueva:

Cuando el dispositivo gira, se destruye la instancia 1 y se crea la instancia 2.

Se trata de una posible pérdida de memoria: el subproceso creado por la primera instancia de la actividad seguirá ejecutándose. Si el subproceso tiene una referencia a la primera instancia de la actividad, esto impedirá que Android recopile el objeto de elementos no utilizados. Sin embargo, se sigue creando la segunda instancia de la actividad (que a su vez podría crear un subproceso). La rotación del dispositivo varias veces en sucesión rápida puede agotar toda la RAM y forzar a Android a finalizar toda la aplicación para reclamar memoria.

Como regla general, si el trabajo que se va a realizar debe sobrevivir a una actividad, se debe crear un servicio para realizar ese trabajo. Sin embargo, si el trabajo solo es aplicable en el contexto de una actividad, la creación de un subproceso para realizar el trabajo podría ser más adecuada. Por ejemplo, la creación de una miniatura para una foto que se acaba de agregar a una aplicación de galería de fotos probablemente debería producirse en un servicio. Sin embargo, un subproceso podría ser más adecuado para reproducir música que solo debería escucharse mientras una actividad está en primer plano.

El trabajo en segundo plano se puede dividir en dos clasificaciones generales:

  1. Tarea de larga duración : este es el trabajo que está en curso hasta que se detiene explícitamente. Un ejemplo de una tarea de larga duración es una aplicación que transmite música o que debe supervisar los datos recopilados de un sensor. Estas tareas se deben ejecutar aunque la aplicación no tenga ninguna interfaz de usuario visible.
  2. Tareas periódicas : (a veces denominadas trabajo) Una tarea periódica es una tarea relativamente corta en duración (varios segundos) y se ejecuta según una programación (es decir, una vez al día durante una semana o quizás solo una vez en los próximos 60 segundos). Un ejemplo de esto es descargar un archivo desde Internet o generar una miniatura para una imagen.

Hay cuatro tipos diferentes de servicios de Android:

  • Servicio enlazado: un servicio enlazado es un servicio que tiene algún otro componente (normalmente una actividad) enlazado a él. Un servicio enlazado proporciona una interfaz que permite que el componente enlazado y el servicio interactúen entre sí. Una vez que no haya más clientes enlazados al servicio, Android apagará el servicio.

  • IntentServiceIntentService: es una subclase especializada de la clase que simplifica la Service creación y el uso del servicio. Está IntentService diseñado para controlar llamadas autónomas individuales. A diferencia de un servicio, que puede controlar simultáneamente varias llamadas, un IntentService es más parecido a un procesador de colas de trabajo : el trabajo se pone en cola y un IntentService proceso de cada trabajo uno a uno en un único subproceso de trabajo. Normalmente, unIntentService no está enlazado a una actividad o a un fragmento.

  • Servicio iniciado: un servicio iniciado es un servicio que ha iniciado algún otro componente de Android (como una actividad) y se ejecuta continuamente en segundo plano hasta que algo indica explícitamente al servicio que se detenga. A diferencia de un servicio enlazado, un servicio iniciado no tiene ningún cliente enlazado directamente a él. Por este motivo, es importante diseñar servicios iniciados para que se puedan reiniciar correctamente según sea necesario.

  • Servicio híbrido: un servicio híbrido es un servicio que tiene las características de un servicio iniciado y un servicio enlazado. Un servicio híbrido se puede iniciar cuando un componente se enlaza a él o puede iniciarse por algún evento. Un componente de cliente puede estar enlazado o no al servicio híbrido. Un servicio híbrido seguirá ejecutándose hasta que se le diga explícitamente que se detenga o hasta que no haya más clientes enlazados a él.

El tipo de servicio que se va a usar depende muy de los requisitos de la aplicación. Como regla general, un IntentService servicio enlazado o son suficientes para la mayoría de las tareas que debe realizar una aplicación Android, por lo que se debe dar preferencia a uno de esos dos tipos de servicios. Es IntentService una buena opción para las tareas "one-shot", como descargar un archivo, mientras que un servicio enlazado sería adecuado cuando se requieren interacciones frecuentes con una actividad o fragmento.

Aunque la mayoría de los servicios se ejecutan en segundo plano, hay una sub categoría especial conocida como servicio en primer plano. Se trata de un servicio que tiene una prioridad más alta (en comparación con un servicio normal) para realizar algún trabajo para el usuario (por ejemplo, reproducir música).

También es posible ejecutar un servicio en su propio proceso en el mismo dispositivo, a veces se conoce como un servicio remoto o como un servicio fuera de proceso. Esto requiere más esfuerzo para crear, pero puede ser útil para cuando una aplicación necesita compartir funcionalidad con otras aplicaciones y, en algunos casos, mejorar la experiencia del usuario de una aplicación.

Límites de ejecución en segundo plano en Android 8.0

A partir de Android 8.0 (nivel de API 26), una aplicación Android ya no tiene la capacidad de ejecutarse libremente en segundo plano. Cuando está en primer plano, una aplicación puede iniciar y ejecutar servicios sin restricciones. Cuando una aplicación se mueve en segundo plano, Android concederá a la aplicación una cantidad determinada de tiempo para iniciar y usar servicios. Una vez transcurrido ese tiempo, la aplicación ya no puede iniciar ningún servicio y se finalizarán los servicios que se iniciaron. En este momento no es posible que la aplicación realice ningún trabajo. Android considera que una aplicación está en primer plano si se cumple una de las condiciones siguientes:

  • Hay una actividad visible (iniciada o en pausa).
  • La aplicación ha iniciado un servicio en primer plano.
  • Otra aplicación está en primer plano y usa componentes de una aplicación que, de lo contrario, estaría en segundo plano. Un ejemplo de esto es si la aplicación A, que está en primer plano, está enlazada a un servicio proporcionado por la aplicación B. La aplicación B también se consideraría en primer plano y Android no terminaría por estar en segundo plano.

Hay algunas situaciones en las que, aunque una aplicación está en segundo plano, Android reactivará la aplicación y relajará estas restricciones durante unos minutos, lo que permitirá que la aplicación realice algún trabajo:

  • La aplicación recibe un mensaje de firebase cloud de prioridad alta.
  • La aplicación recibe una difusión.
  • La aplicación recibe y ejecuta un objeto PendingIntent en respuesta a una notificación.

Es posible que las aplicaciones de Xamarin.Android existentes tengan que cambiar el funcionamiento en segundo plano para evitar cualquier problema que pueda surgir en Android 8.0. Estas son algunas alternativas prácticas a un servicio Android:

  • Programar el trabajo para ejecutarse en segundo plano mediante el programador de trabajos de Android o el distribuidor de trabajos de Firebase: estas dos bibliotecas proporcionan un marco para que las aplicaciones separe el trabajo en segundo plano en los trabajos, una unidad discreta de trabajo. A continuación, las aplicaciones pueden programar el trabajo con el sistema operativo junto con algunos criterios sobre cuándo se puede ejecutar el trabajo.
  • Iniciar el servicio en primer plano : un servicio en primer plano es útil para cuando la aplicación debe realizar alguna tarea en segundo plano y es posible que el usuario tenga que interactuar periódicamente con esa tarea. El servicio en primer plano mostrará una notificación persistente para que el usuario tenga en cuenta que la aplicación está ejecutando una tarea en segundo plano y también proporciona una manera de supervisar o interactuar con la tarea. Un ejemplo de esto sería una aplicación de podcasts que está reproduciendo un podcast al usuario o quizás descargar un episodio de podcast para que se pueda disfrutar más adelante.
  • Usar un mensaje en la nube de Firebase de alta prioridad (FCM): cuando Android recibe un FCM de alta prioridad para una aplicación, permitirá que esa aplicación ejecute servicios en segundo plano durante un breve período de tiempo. Esta sería una buena alternativa a tener un servicio en segundo plano que sondee una aplicación en segundo plano.
  • Aplazar el trabajo para cuando la aplicación entra en primer plano : si ninguna de las soluciones anteriores es viable, las aplicaciones deben desarrollar su propia manera de pausar y reanudar el trabajo cuando la aplicación llega al primer plano.