Broadcast Receivers para escuchar eventos del sistema en Android

Clase 32 de 33Curso de Android: Integración de APIs nativas

Resumen

Escuchar y responder a eventos específicos es fundamental en aplicaciones Android. Los broadcast receivers son precisamente los encargados de escuchar eventos emitidos por el sistema operativo o eventos personalizados creados por la aplicación. Eventos comunes incluyen conexiones USB o cambios en el modo avión.

¿qué es un Broadcast Receiver?

Un broadcast receiver es un componente esencial para reaccionar a eventos específicos que se generan dentro o fuera de una aplicación. Pueden escuchar desde eventos del propio sistema operativo hasta eventos personalizados definidos por el desarrollador.

¿Cómo crear un Broadcast Receiver personalizado?

Crear un receptor propio requiere definir una clase que extienda de BroadcastReceiver e implemente el método onReceive:

class StopReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        val action = intent?.action ?: return
        if (action != ACTION_STOP) return
        // Lógica para detener la actividad o servicio pertinente.
    }

    companion object {
        const val ACTION_STOP = "trackit.action.stoptracking"
    }
}

Para manejar eventos con eficacia, es importante validar que el mensaje recibido no sea nulo y coincida con la acción esperada.

¿Qué operaciones se ejecutan al recibir un evento?

Al recibir el evento de detención, es necesario realizar una serie de tareas que involucran:

  • Establecer el estado de tracking como desactivado.
  • Detener la observación de la localización.
  • Limpiar recursos, como fotografías almacenadas.

Estas tareas son realizadas habitualmente sobre un scope de coroutine, asegurando la finalización de cada proceso:

applicationScope.launch {
    locationTracker.setIsTracking(false)
    locationTracker.stopObservingLocation()
    photoHandler.clearPhotos().join()
}

Tras esto, se envía un comando para detener el servicio asociado:

val serviceIntent = Intent(context, TrackingService::class.java).apply {
    action = TrackingService.ACTION_STOP
}
if (TrackingService.isActive.value) {
    context?.startService(serviceIntent)
}

¿Cómo registrar un Broadcast Receiver en Android?

Todos los receptores deben registrarse correctamente desde el archivo Manifest de la aplicación:

<receiver android:name=".StopReceiver" android:exported="false"/>

El parámetro exported indica si otras aplicaciones podrían activar este receptor; habitualmente, se establece en false.

¿De qué forma interactúa un Broadcast Receiver con notificaciones?

El uso de un pending intent permite agregar acciones a las notificaciones, enviando mensajes a nuestro receptor para ejecutar eventos específicos aunque la aplicación esté cerrada:

val stopIntent = Intent(applicationContext, StopReceiver::class.java).apply {
    action = StopReceiver.ACTION_STOP
}

val stopPendingIntent = PendingIntent.getBroadcast(applicationContext, 0, stopIntent, PendingIntent.FLAG_IMMUTABLE)

Al incorporar esta intención en la notificación, se vincula la interacción del usuario directamente al receptor personalizado:

notificationBuilder.addAction(R.drawable.ic_launcher_foreground, applicationContext.getString(R.string.stop), stopPendingIntent)

Al pulsar esta acción en la notificación, la aplicación se activa y ejecuta las tareas correspondientes establecidas en el receptor de eventos.

¿Has utilizado antes broadcast receivers para manejar eventos específicos en tus aplicaciones? Comparte tu experiencia o dudas en los comentarios.