Contenido del curso
Google Maps SDK
Servicios de Localización
- 7

Kotlin Flows para medir tiempo en Android
12:54 min - 8

Simulación de ubicación GPS en emulador y dispositivo Android
05:48 min - 9

Modelos de localización propios con Clean Architecture
08:36 min - 10

Callbacks de Android convertidos en Flows
14:50 min - 11

Inyección de dependencias para observar localización en Android
06:33 min - 12

LocationTracker con StateFlow para rastreo en Android
08:46 min - 13

State Flows para controlar localización y tiempo en Kotlin
10:00 min - 14

Configuración y pruebas de Location Tracker en Android
09:37 min
Integración Maps con Localización
Manejo de permisos
Integración cámara
- 23

Cómo guardar fotos en Android con PhotoHandler
11:59 min - 24

Conversión de Bitmaps a Byte Arrays con Extension Functions
05:58 min - 25

CameraViewModel con Hilt y StateFlow
08:40 min - 26

Configuración de métodos del ViewModel para gestión de cámara
09:40 min - 27

Integración de CameraX con Jetpack Compose en Android
14:23 min - 28

Creación de pantalla de previsualización de fotos con Jetpack Compose
08:44 min - 29

Galería de fotos en marcadores del mapa
11:55 min
Servicios en Android
Transmisiones en Android (Broadcast)
Servicios en segundo plano en Android
Resumen
Crear un Service en Android te permite ejecutar tareas en segundo plano, como hacer tracking de la ubicación del usuario mientras la app no está visible. Aquí aprenderás a implementar un servicio normal con Kotlin, inyección de dependencias con Hilt y corutinas, entendiendo por qué este tipo de servicio no garantiza persistencia cuando el sistema operativo libera recursos.
Qué componentes principales tiene Android
Android se construye sobre varios bloques que cumplen funciones específicas dentro de una aplicación.
Los dos protagonistas de esta clase son las activities y los services. Las primeras muestran la interfaz de usuario mediante composables; los segundos ejecutan procesos en segundo plano sin interfaz visible.
¿Qué es un Service en Android? Es un componente que ejecuta operaciones de larga duración en segundo plano sin interfaz de usuario, ideal para tareas como rastrear la ubicación o reproducir audio.
Cuál es la diferencia entre service y foreground service
Los services normales y los foreground services se diferencian por su prioridad ante el sistema operativo:
- Los services normales no tienen garantía de persistencia. Si el sistema necesita liberar recursos, los termina sin aviso.
- Los foreground services tienen prioridad alta y siguen activos aunque cierres la aplicación.
- La condición de un foreground service es mostrar una notificación visible mientras el proceso esté corriendo.
Cómo crear un service con inyección de dependencias en Kotlin
Dentro de la carpeta del proyecto creamos la clase TrackitService y la anotamos con @AndroidEntryPoint para habilitar Hilt. La clase debe extender de Service, lo que obliga a implementar el método onBind, que en este caso devuelve null porque no vamos a ligar la actividad con el servicio.
Luego inyectamos el locationTracker como dependencia. A diferencia de las activities o los ViewModels, un servicio no trae un scope propio, así que debemos crearlo manualmente con CoroutineScope(Dispatchers.Main + SupervisorJob()). Este scope nos permite lanzar corutinas controladas dentro del ciclo de vida del servicio.
Cómo controlar el estado del servicio con StateFlow
Para evitar iniciar el servicio dos veces, declaramos una variable interna _isServiceActive y la exponemos públicamente con asStateFlow(). Así, cualquier composable puede consultar si el servicio ya está corriendo.
En un companion object definimos dos constantes que actúan como comandos:
ACTION_STARTpara iniciar el seguimiento.ACTION_STOPpara detenerlo.- Una variable mutable
isServiceActiveque cambia de estado según el flujo.
¿Qué es un Intent en Android? Es un mensaje que comunica componentes del sistema, por ejemplo, una activity enviando una orden a un service para iniciar o detener una acción.
Cómo implementar onStartCommand y manejar el ciclo del servicio
El método onStartCommand recibe el intent con la acción enviada desde la actividad. Dentro de él hacemos un when sobre intent?.action y disparamos start() o stop() según el comando.
Devolvemos START_STICKY, una bandera que le indica al sistema que intente reiniciar el servicio si fue terminado, reutilizando la misma instancia cuando sea posible.
Qué hacen las funciones start y stop
La función start valida si el servicio ya está activo. Si no lo está, cambia la bandera a true y lanza una corutina dentro del serviceScope que escucha el elapsedTime del locationTracker con onEach, imprimiendo un log con el tiempo transcurrido.
La función stop hace lo contrario:
- Cambia
isServiceActiveafalse. - Cancela el
serviceScopeactual con todas sus tareas asociadas. - Crea un nuevo
CoroutineScopeconSupervisorJob, porque las corutinas canceladas no se pueden reutilizar.
Por eso serviceScope debe declararse como var y no como val: necesitamos reasignarlo cuando reactivemos el servicio.
Cómo declarar el service en el AndroidManifest
Ningún componente de Android funciona si no está registrado en el AndroidManifest.xml. Dentro del bloque <application>, junto a las activities, agregamos la etiqueta <service> apuntando a TrackitService. Sin este paso, el sistema operativo bloqueará la inicialización del servicio.
Cómo invocar el service desde un Composable
En la MapScreen, cuando el usuario concede los permisos de ubicación, construimos un Intent apuntando a TrackitService::class.java y le asignamos el action:
kotlin val intent = Intent(context, TrackitService::class.java).apply { action = TrackitService.ACTION_START }
Antes de lanzarlo, verificamos con if (!TrackitService.isServiceActive.value) que no esté ya corriendo. Esta misma lógica se reutiliza en el LaunchedEffect para resumir el tracking si el usuario vuelve a la pantalla, y en el onClick del floating action button dentro de un when que distingue entre iniciar, pausar o reanudar el recorrido.
Por qué un service normal no persiste en segundo plano
Al probar la app en el emulador, el contador de tiempo avanza normalmente. Si llevas la aplicación a segundo plano, el conteo continúa. Pero al hacer slide sobre la tarjeta de la app y matar la actividad, el sistema operativo termina el proceso aproximadamente a los 33 segundos.
Esto pasa porque un service normal no recibe prioridad. Para mantener un proceso vivo incluso cuando el usuario cierra la app, necesitas un foreground service, que es justo el siguiente paso en el aprendizaje.
¿Has tenido que implementar tracking en segundo plano en alguna app? Cuéntame qué desafíos te encontraste con la persistencia de procesos.