Servicios de Android mediante Módulos Nativos de React Native

Hoy quiero compartir con ustedes la segunda parte de mi post de módulos nativos en React Native. Este post tratará de mostrar de forma sencilla y didáctica, como crear un servicio en Android y como manipularlo mediante el uso de Módulos Nativos. Es importante destacar que el foco está en el servicio y no en cómo crear un módulo, por lo que si aún no leyeron mi post anterior, se los recomiendo.


Un servicio

Antes de comenzar a crear un servicio debemos establecer primero qué significa.

Un servicio, según la propia documentación de android, 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”

Esto quiere decir que nos permite crear distintos tipos de funcionalidades que no necesariamente deban tener interacción con el usuario. Los servicios se correrán en segundo plano, dentro de nuestra aplicación, e incluso podrán vivir por fuera de la misma, si así lo especificamos. Es importante que el servicio creado administre su propio ciclo de vida, ya que de otra forma no será eliminado a menos que el S.O requiera liberar memoria.

Aquí pueden investigar con más detalle los conceptos básicos y los tipos de servicios para Android.

Para manejar el servicio utilizando nuestro Framework favorito, vamos a requerir de la implementación de un módulo nativo, que nos permita acceder a la creación del mismo desde nuestro código JS, e incluso compartir información entre el Módulo y el Servicio.

¿Qué podemos hacer con un servicio?

Para poner en práctica nuestras habilidades con los servicios, vamos a realizar una sencilla aplicación, aprovechando el ejemplo que creamos en la parte 1 de este post. Si no lo tienes en claro, puedes revisarlo AQUÍ. Una vez comprendido el concepto, podremos hacer todo lo que se nos ocurra.

¡Una breve pero importante aclaración al respecto!
A partir de Android Oreo, se implementaron ciertas limitaciones para los servicios que corren en background. Para mayor información al respecto, los invito a visitar este Post donde se explica de forma clara cuáles son los cambios y cómo afectan a las apps que desean utilizar servicios en background. Además, pueden leer la documentación oficial de Android Aquí.

El próximo ejemplo consistirá en crear un servicio que permanezca inspeccionando el estado de conexión de nuestro dispositivo, compartiendo información con el usuario, para indicarle qué tipo de conexión tiene o si no dispone de conexión. Hasta aquí tenemos lo mismo que realizamos en la parte 1, pero la diferencia es que nuestro servicio será capaz de trabajar en segundo plano por fuera de nuestra aplicación. Agregaremos un mensaje mediante un Toast que le indique al usuario que pasó determinado tiempo sin tener conexión. ¿Comenzamos?


Ejemplo

Servicio

Vamos a comenzar creando el archivo que será nuestro servicio. Para ello creamos un archivo llamado “ConnectionNotificationService.java” dentro de “java/com.awesomeproject”. Declararemos una clase llamada “ConnectionNotificationService” la cual extenderá de “Service”. Luego declararemos los atributos que utilizaremos y un método importante para mantener una comunicación entre el módulo y el servicio.

“setUpdateListener” nos permitirá obtener una referencia del módulo nativo, por el cual podremos enviar información desde nuestro servicio.

Luego crearemos la función “onCreate” en la cual vamos a comenzar a consumir el servicio del sistema que nos permitirá conocer el estado de conexión del dispositivo. A continuación crearemos un contador de 10 segundos el cual comprueba el estado de conexión cada 1 segundo y vuelve a reiniciarse si llega a 10, como un loop infinito.

Específicamente, “checkConnectionStatus” , extraída como un método, por comodidad y visibilidad de código, será quien chequee el estado de conexión y realice acciones a partir de los resultados.

La primer parte es igual a lo que hacíamos anteriormente en el modulo native, en la parte 1 del post. Por otro lado, los métodos “stop” y “startMissingConnectionTimer” serán los contadores que utilizaremos para saber que el dispositivo permaneció sin conexión. El flujo sería el siguiente:

Si se chequea que el estado de conexión es nulo, entonces comenzaremos a contar hasta 10 segundos. Si dentro de esos 10 segundos, la conexión se restableció, se cancelará el contador, caso contrario, se mostrará un Toast al usuario con un pequeño y amigable mensaje.

En caso de que se cumpla la condición de 10 segundos sin conexión, automáticamente el Servicio se detendrá gracias al “stopSelf()” y dejara de consumir recursos.

Para finalizar crearemos el método “onDestroy” donde limpiaremos las referencias y detendremos los Timers en funcionamiento.

Para este punto, la clase deberá visualizarse de la siguiente manera:

Módulo Nativo

Para esta sección, vamos a reutilizar el módulo nativo que creamos previamente en la parte 1 del post.

Te habrás preguntado de dónde vienen los métodos “setModuleParams” y “removeServiceReference” invocados desde “mModuleManager”. Bueno, como ya habrás adivinado, estas funciones provienen del ModuleManager, dado que como antes mencionamos, en “setUpdateListener” obtendremos una referencia para mantener un canal de comunicación abierto entre el módulo y el servicio.

Veamos entonces los 3 métodos que necesitamos crear en “ConnectionStatusModuleManager.java”

Con “setModuleParams” vamos a guardarnos la información proveniente del servicio en los atributos de la clase “ConnectionStatusModuleManager” para luego enviárselos a JS cuando sea requerido.

Con “removeServiceReference” eliminaremos la referencia que tengamos del servicio creado.

Finalmente el “@ReactMethod” “checkConnectionStatus” será el invocado por JS para obtener la información del estado del dispositivo y el responsable de crear el servicio en caso de que el mismo aún no se haya creado.

Debemos notar que

“ConnectionNotificationService.setUpdateListener(this);”

Le enviará al service una referencia para abrir el canal de comunicación antes mencionado.

Llegando al final

Lo necesario para que nuestro servicio funcione está casi listo, pero antes de terminar vamos a hacer un pequeño repaso del flujo dado hasta el momento.

Inicialmente, el módulo nativo, al ser llamado por JS, intentará crear un servicio nuevo y comenzará a enviarle los valores recolectados de status y name a JS.

El servicio, el cual correrá en segundo plano, al iniciarse creará un bucle infinito de un contador que actualizará (gracias a la comunicación entre el módulo y el servicio) cada 1 segundo el estado de conexión durante 10 segundos y luego reiniciará el conteo.

En caso de no disponer de conexión, se iniciará paralelamente, un segundo contador el cual contará hasta 10 para luego enviarle un mensaje al usuario mediante un Toast. En caso de que dentro de los 10 segundos, se restablezca la conexión, el contador se cancelara. Si el Toast es disparado, el servicio se autodestruirá pero si estamos dentro de la app volverá a iniciarse. En caso de que se dispare fuera de la app, el servicio se auto destruirá y no volverá a crearse.

Habiendo repasado el flujo que creamos, solo nos queda declarar el servicio dentro del manifest. Para ello, agregaremos lo siguiente dentro de “application”.

App JS

Finalmente nuestro módulo y servicio están finalizados. Como reutilizamos el proyecto de la parte 1 del post, no es necesario cambiar nada de “app.js” , sin embargo podemos modificar el timeout a 1 segundo, para obtener más rápidamente la información proveniente del servicio.

Las declaraciones quedarían de la siguiente manera:

El momento de la verdad

Ahora que tenemos todo listo, solo queda buildear nuestra nueva aplicación para ser informados sobre la falta de conexión. Deberíamos poder ver algo como esto:


Espero que este post los haya ayudado a comprender y a poner en práctica todas las ideas que hayan tenido, incluso aquellas que parecían imposibles. Mediante servicios podremos extender funcionalidades por detrás de la app e incluso por fuera de la misma. Algunas funcionalidades conocidas pueden ser reproductores de música, grabación de audio de llamadas, verificador de estados, administración de descargas y todo lo que puedan imaginar.

Si esta serie de posts fue de su agrado, no duden en regalarme sus aplausos y comentar o preguntar cualquier duda que les surja. Recuerden que el límite de sus creaciones solo está en donde ustedes quieran ponerlo.

Like what you read? Give Ignacio Abadie a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.