Android y Laravel: Envío de notificaciones FCM

El envío de notificaciones Android es muy importante.

Las notificaciones nos permiten informar a nuestros usuarios de eventos, a medida que estos ocurren, minutos antes de que ocurran, o incluso posteriormente en forma de recordatorio.

El envío apropiado de notificaciones se asocia con la ejecución de tareas recurrentes en el servidor, que determinan cuándo es conveniente enviar notificaciones, sin abusar de la frecuencia.

Hoy veremos cómo enviar una notificación general a todos los usuarios, desde un panel administrativo.

Este punto de partida te permitirá enviar notificaciones bajo distintas circunstancias, según los requerimientos de tu aplicación.

FCM: Firebase Cloud Messaging

Las notificaciones Android que usaremos estarán potenciadas por esta tecnología llamada FCM.

No es exclusivo de Android. FCM está disponible también para iOS, aplicaciones Web, juegos desarrollados en Unity y proyectos C++.

Vayamos a lo que nos interesa, viendo paso a paso los cambios a realizar en nuestro proyecto Android.

FCM en Android

Cuando se envía una notificación Android, ésta puede recibirse en distintos tipos de clientes. En este caso nuestra aplicación Android será un cliente, que recibirá una notificación de parte de un servidor, que hace el envío.

Como el mismo nombre lo indica (Firerbase Cloud Messaging), este es un servicio que forma parte de la suite de Firebase. Entonces lo primero es integrar Firebase a nuestro proyecto Android.

Si ya tienes Firebase en tu proyecto puedes saltar la sección siguiente, que está dedicada para aquellos que no.

Firebase en Android

Tal como se observa en la imagen, lo primero es acceder a la consola de Firebase y crear un proyecto Firebase nuevo.

Crear proyecto en la consola de Firebase

Para este ejemplo voy a integrar Firebase sobre un proyecto llamado Km0.

Nombre e ID del proyecto Firebase

Tras ingresar el nombre y asociar una cuenta de Google Analytics por recomendación de Firebase ya tengo el proyecto creado.

Proyecto Firebase creado

Si sigues estos pasos llegarás al Dashboard de tu proyecto. Allí debes hacer clic en el botón con el ícono de Android para iniciar con la configuración.

Integrar Firebase a un proyecto Android

En este punto Firebase nos solicita el "package name" de nuestro proyecto. Si no lo recuerdas puedes encontrarlo en tu archivo AndroidManifest.xml.

Opcionalmente también puedes agregar un Alias para el proyecto.

Y entonces Firebase te permitirá descargar un archivo de configuración. Este archivo (llamado google-services.json) debes agregarlo a la carpeta app de tu proyecto Android.

Descargar archivo de configuración

Por último agregamos el SDK de Firebase a nuestro proyecto y habilitamos Google Play Services.

Luego de modificar los build.gradle a nivel de proyecto y módulo, presionamos "Sync Now" y ejecutamos nuestra aplicación nuevamente para que Firebase nos informe si nos hemos comunicado con sus servidores correctamente.

En pocos segundos recibirás la confirmación:

Confirmación de Firebase

Aplicación Android cliente de FCM

Para que nuestra aplicación sea cliente de Firebase Cloud Messaging, empecemos agregando el SDK de FCM a nuestro proyecto.

Puedes hacer ello agregando esta línea en tu archivo build.gradle (a nivel de Module):

implementation 'com.google.firebase:firebase-messaging:20.1.0'

Como segundo paso editamos nuestro AndroidManifest, agregando un elemento <service> al interior de <application>.

<service
    android:name=".io.fcm.FCMService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

Esto permitirá que la clase FCMService dentro de /io/fcm reciba información de las notificaciones.

Es un ejemplo, por lo que el nombre de la clase y su ubicación pueden cambiar, si lo crees conveniente.

Y respecto al contenido de la clase, puedes usar esta clase FCMService.kt como guía.

En esta clase que te comparto encontrarás cosas que pueden cambiar según tu proyecto.

Por ejemplo:

Si quieres aprender más sobre estos 2 últimos te recomiendo seguir el curso que tengo publicado en Udemy, sobre Android y Laravel.

Obtener el FCM token de cada usuario

En la clase que te comentaba antes, tenemos un método onNewToken que es invocado cada vez que el token cambia (hay un proceso de refresh que ocurre cada cierto tiempo, y es importante guardar el token para que el usuario pueda recibir notificaciones de manera específica cuando se necesite).

¿Qué hacer en este método?

override fun onNewToken(newToken: String) {
    super.onNewToken(newToken)

    val jwt = preferences["jwt", ""]
    if (jwt.isEmpty()) return

    val authHeader = "Bearer $jwt"

    val call = apiService.postToken(authHeader, newToken)
    call.enqueue(object: Callback<Void> {
        override fun onFailure(call: Call<Void>, t: Throwable) {
            toast(t.localizedMessage)
        }

        override fun onResponse(call: Call<Void>, response: Response<Void>) {
            if (response.isSuccessful) {
                Log.d(TAG, "Token registrado correctamente")
            } else {
                Log.d(TAG, "Hubo un problema al registrar el token")
            }
        }
    })
}

En el ejemplo anterior, ocurre lo siguiente:

  • Primero accedo a las preferencias para ver si hay un JSON Web Token (es decir, una sesión de usuario en la aplicación)
  • Luego preparamos un Authorization header para que la petición al servidor incluya el JWT, y de esta manera el dato se pueda asociar al usuario
  • Por último, usamos un API Service para llevar a cabo la petición y registrar el token en nuestro servidor

Este código en Android es válido para cualquier tecnología backend que implemente los endpoints adecuados. Una alternativa es implementar la API con Laravel.

Existen alternativas a Laravel, como Lumen, si sólo se pretende desarrollar una API.

Pero si también tenemos un proyecto web (un panel administrativo con reportes en este caso), entonces podemos aprovechar el mismo proyecto Laravel.

Nota: en el último ejemplo notarás que usé toast para mostrar un Toast sin escribir una línea extensa como es usual. Eso también es gracias a la definición de una extension function.

Registrando el FCM token en el servidor

Para que una comunicación sea segura, es importante usar el protocolo HTTPS. De esta manera los datos viajan seguros hasta llegar al servidor.

Usar JSON Web Tokens es añadir una capa adicional de seguridad, para que, en vez de enviar las credenciales de un usuario por cada solicitud al servidor, se envíe un JWT que represente su sesión.

Los JWT funcionan de manera diferente a cómo funcionan las Cookies, que se han usado tradicionalmente para representar sesiones de usuarios en un navegador.

Todo esto, lo revisamos con detenimiento en el curso de Android y Laravel. Por lo que si aún no te has inscrito, te invito a hacerlo 🙂

En resumen, nuestra API tendría una ruta declarada (usualmente en routes\api.php):

Route::post('/fcm/token', '[email protected]');

Esta ruta o endpoint será atendida por un controlador. En este caso, a través de un método store en FirebaseController.

Es así que sólo debemos identificar al usuario por su JWT, y guardar su correspondiente FCM Token (el que le asigna Firebase, para poder enviarle notificaciones luego):

public function postToken(Request $request)
{
    $user = Auth::guard('api')->user();

    if ($request->has('device_token')) {
        $user->device_token = $request->input('device_token');
        $user->save();
    }
}

Enviar notificación a todos los usuarios

De lado de nuestro proyecto web podemos crear un formulario con 2 campos:

Formulario de envío

La idea es que este formulario haga una petición POST a una ruta. Por ejemplo, puedes tener una ruta como la siguiente en routes\web.php:

Route::post('/fcm/send', '[email protected]');

De tal manera, que en el método sendAll de nuestro Admin\FirebaseController tengamos algo como lo siguiente:

public function sendAll(Request $request)
{
    $recipients = User::whereNotNull('fcm_token')
        ->pluck('fcm_token')->toArray();

    fcm()
        ->to($recipients)
        ->notification([
            'title' => $request->input('title'),
            'body' => $request->input('body')
        ])
        ->send();

    $notification = 'Notificación enviada a todos los usuarios (Android).';
    return back()->with(compact('notification'));
}

En el ejemplo anterior obtenemos la lista de usuarios que tienen un token asociado (es decir, usuarios que han usado nuestra aplicación).

Luego, hacemos una petición a FCM, para que les envíe una notificación a todos ellos, usando el título y mensaje ingresados en el formulario.

Puedes pedirle ello a FCM de múltiples maneras. Por ejemplo, a través de una petición HTTP, enviando las credenciales de tu aplicación.

En el código de arriba todo ello se ve simplificado debido a que usé un paquete de Laravel para FCM, y las credenciales están indicadas en un archivo de configuración.

Obtener el FCM token en cualquier momento

Anteriormente comentamos que el método onNewToken en nuestro FCMService se llama cada vez que el token se actualiza.

¿Pero qué ocurre si un usuario cambia de dispositivo o inicia sesión por primera vez?

Para asegurar que disponemos del valor adecuado podemos acceder al token justo después de que el usuario ha iniciado sesión, y así registrar su valor.

Esto es posible de la siguiente manera:

FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener(this) { instanceIdResult ->
    val deviceToken = instanceIdResult.token

    // Aquí es posible hacer una petición POST a nuestra API para registrar el token
}

Conclusión

Como ves, las notificaciones son un tema muy interesante y su uso está asociado a otros conceptos, tales como:

La intención de este artículo es explicar en términos generales cómo funciona el envío de notificaciones push vía Firebase Cloud Messaging.

Si quieres aprender más de estos temas, te invito a seguir el curso de Laravel y Android que tengo publicado en Udemy, donde todas tus dudas serán bienvenidas.

# laravel # android # retrofit # jwt

Cursos recomendados

Curso de Laravel y OAuth 2 (Login con redes sociales)

Laravel y OAuth2

Veamos cómo implementar un login mediante redes sociales! Aprende y aplica esto sobre cualquier proyecto Laravel.

Ingresar al curso
Curso intensivo de Laravel y Android

Laravel y Android

Curso intensivo que incluye el desarrollo de una API, su consumo, y autenticación vía JWT. También vemos Kotlin desde 0.

Ingresar al curso
Curso práctico de Javascript

Aprende Javascript

Domina JS con este curso práctico y completo! Fundamentos, ejemplos reales, ES6+, POO, Ajax, Webpack, NPM y más.

Ingresar al curso
Logo de Programación y más

¿Tienes alguna duda?

Si algo no te quedó claro o tienes alguna sugerencia, escribe un comentario aquí debajo.

Además recuerda compartir el post si te resultó de ayuda! 🙂

Cargando comentarios ...

Antes que te vayas

Inscríbete en nuestro curso gratuito de Laravel