Skip to Content
Migrando desde FBG

🚀 Guía de migración: flutter_background_geolocation → Tracelet

¿Cambiar de flutter_background_geolocation a Tracelet? ¡Gran elección! Tracelet es una alternativa totalmente de código abierto (Apache 2.0) con una API compatible 1:1, además de extras como filtrado Kalman, detección simulada, zonas de privacidad y más. Sin claves de licencia, sin SDK propietarios, código fuente completo.

💡 Esta guía siempre refleja la versión actual.


⚡ Carrera rápida de 3 pasos

En serio, es así de rápido.

Paso 1: intercambiar la dependencia:

# Before dependencies: flutter_background_geolocation: ^5.x.x

Después ✨

dependencies: tracelet: ^3.6.14

Paso 2: Actualizar importaciones:

// Before import 'package:flutter_background_geolocation/flutter_background_geolocation.dart' as bg; // After — short & sweet ✅ import 'package:tracelet/tracelet.dart' as tl;

Paso 3: busque y reemplace el nombre de la clase:

// Before bg.BackgroundGeolocation.ready(bg.Config(...)); // After tl.Tracelet.ready(tl.Config.balanced().copyWith(...));

Eso es literalmente todo. Cada método, cada evento, cada devolución de llamada: compatible 1:1. El resto de esta guía es sólo una hoja de referencia para los detalles.


🏗️ Configuración: de plana a estructurada

El complemento anterior utiliza un único Config() plano con todos los campos en un nivel. Tracelet los organiza en secciones lógicas, lo que hace que las configuraciones grandes sean mucho más fáciles de leer y mantener.

// Before — flat config bg.Config( desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH, distanceFilter: 10.0, stopOnTerminate: false, startOnBoot: true, stopTimeout: 5, url: 'https://api.example.com/locations', batchSync: true, autoSync: true, headers: {'Authorization': 'Bearer $token'}, heartbeatInterval: 60, notification: bg.Notification(title: 'Tracking', text: 'Active'), debug: true, logLevel: bg.Config.LOG_LEVEL_VERBOSE, ); // After — organized by section 🏠 tl.Config( geo: tl.GeoConfig( desiredAccuracy: tl.DesiredAccuracy.high, // typed enums! distanceFilter: 10.0, ), app: tl.AppConfig( stopOnTerminate: false, startOnBoot: true, heartbeatInterval: 60, ), android: tl.AndroidConfig( foregroundService: tl.ForegroundServiceConfig( notificationTitle: 'Tracking', notificationText: 'Active', ), ), motion: tl.MotionConfig( stopTimeout: 5, ), http: tl.HttpConfig( url: 'https://api.example.com/locations', batchSync: true, autoSync: true, headers: {'Authorization': 'Bearer $token'}, ), logger: tl.LoggerConfig( debug: true, logLevel: tl.LogLevel.verbose, // readable enum instead of int constants ), );

Las secciones de configuración de un vistazo:

  • geoGeoConfig — Precisión, filtro de distancia, elasticidad, modo periódico, filtro de Kalman, detección simulada
  • appAppConfig — Ciclo de vida, latidos, programación
  • androidAndroidConfig — 🆕 Solo Android: notificación de servicio en primer plano, intervalos de actualización de ubicación, AlarmManager, estrategias periódicas
  • iosIosConfig — 🆕 Solo iOS: tipo de actividad, sesiones en segundo plano, evitar suspensión
  • motionMotionConfig — Tiempo de espera de parada, reconocimiento de actividad, modo solo acelerómetro
  • httpHttpConfig: URL de sincronización, encabezados, procesamiento por lotes, reintento de retroceso, modo solo Wi-Fi
  • loggerLoggerConfig — Nivel de registro, días máximos, sonidos de depuración
  • geofenceGeofenceConfig — Radio de proximidad, disparador inicial, modo knock-out
  • persistencePersistenceConfig — Modo persistente, máximo de días/registros, plantillas
  • auditAuditConfig — 🆕 Cadena hash SHA-256 — porque la seguridad es importante
  • privacyZonePrivacyZoneConfig — 🆕 Motor de zonas de privacidad — El mejor amigo del RGPD
  • securitySecurityConfig — 🆕 Cifrado de base de datos en reposo (encryptDatabase)
  • attestationAttestationConfig — 🆕 Verificaciones de integridad/certificación del dispositivo

🗺️ La hoja de referencia de la gran configuración

No te preocupes, cada campo tiene un mapeo 1:1. Aquí está tu Piedra Rosetta.

Ubicación y seguimiento → GeoConfig

Before → Tracelet ───────────────────────────────────────────────────────────── desiredAccuracy (int: -2…100) → geo.desiredAccuracy (DesiredAccuracy enum) .high / .medium / .low / .veryLow / .passive distanceFilter → geo.distanceFilter (default 10m) stationaryRadius → geo.stationaryRadius (default 25m) locationTimeout → geo.locationTimeout (default 60s) disableElasticity → geo.disableElasticity elasticityMultiplier → geo.elasticityMultiplier (default 1.0) stopAfterElapsedMinutes → geo.stopAfterElapsedMinutes (-1 = disabled) enableTimestampMeta → geo.enableTimestampMeta maxMonitoredGeofences → geo.maxMonitoredGeofences (-1 = platform default)

Campos específicos de Android → AndroidConfig:

Before → Tracelet ───────────────────────────────────────────────────────────── locationUpdateInterval → android.locationUpdateInterval (1000ms) fastestLocationUpdateInterval → android.fastestLocationUpdateInterval (500ms) deferTime → android.deferTime allowIdenticalLocations → android.allowIdenticalLocations geofenceModeHighAccuracy → geofence.geofenceModeHighAccuracy (cross-platform; android.* is deprecated) scheduleUseAlarmManager → android.scheduleUseAlarmManager

Campos específicos de iOS → IosConfig:

Before → Tracelet ───────────────────────────────────────────────────────────── activityType → ios.activityType (LocationActivityType enum) useSignificantChangesOnly → ios.useSignificantChangesOnly showsBackgroundLocationIndicator → ios.showsBackgroundLocationIndicator pausesLocationUpdatesAutomatically → ios.pausesLocationUpdatesAutomatically locationAuthorizationRequest → ios.locationAuthorizationRequest disableLocationAuthorizationAlert → ios.disableLocationAuthorizationAlert preventSuspend → ios.preventSuspend

🆕 Campos GeoConfig exclusivos de Tracelet:

  • geo.enableAdaptiveMode — Adapta el filtro de distancia por actividad + batería + velocidad
  • geo.periodicLocationInterval: 900 predeterminados (15 min)
  • geo.periodicDesiredAccuracy: .medium predeterminado
  • geo.filter (LocationFilter) — Kalman, detección simulada, umbrales de precisión

🧹 Filtro de ubicación → LocationFilter (¡exclusivo de Tracelet!)

  • 🆕 filter.policyLocationFilterPolicy.adjust / .ignore / .discard
  • 🆕 filter.useKalmanFilter — Filtro Kalman extendido de 4 estados: suaviza el ruido del GPS como un profesional
  • 🆕 filter.mockDetectionLevel.disabled / .basic / .heuristic — detecta esas ubicaciones falsas
  • 🆕 filter.rejectMockLocations — Ubicaciones simuladas de rechazo automático
  • 🆕 filter.maxImpliedSpeed — Filtro de picos — “no, el usuario NO se teletransportó”
  • 🆕 filter.trackingAccuracyThreshold — Precisión mínima para aceptar
  • 🆕 filter.odometerAccuracyThreshold — Precisión mínima para actualizaciones del odómetro

Detección de movimiento → MotionConfig

Before → Tracelet ───────────────────────────────────────────────────────────── stopTimeout → motion.stopTimeout (default 5 min) motionTriggerDelay → motion.motionTriggerDelay disableMotionActivityUpdates → motion.disableMotionActivityUpdates (set true for accelerometer-only, no permission!) isMoving → motion.isMoving (initial state) activityRecognitionInterval → motion.activityRecognitionInterval (10000ms) minimumActivityRecognitionConfidence → motion.minimumActivityRecognitionConfidence (75) disableStopDetection → motion.disableStopDetection stopDetectionDelay → motion.stopDetectionDelay stopOnStationary → motion.stopOnStationary triggerActivities → motion.activityTypes (Set<ActivityType>)

🆕 Campos MotionConfig exclusivos de Tracelet:

  • motion.motionDetectionMode.accelerometer / .speed / .smart — cómo se detecta el movimiento (inteligente = acelerómetro y velocidad del GPS; recomendado)
  • motion.shakeThreshold: ajuste solo del acelerómetro (predeterminado 2.5)
  • motion.stillThreshold: ajuste solo del acelerómetro (predeterminado 0.4)
  • motion.stillSampleCount: ajuste solo del acelerómetro (predeterminado 25)
  • motion.speedMovingThreshold / motion.speedStationaryDelay / motion.speedWakeConfirmCount — ajuste del modo de velocidad (utilizado por .speed / .smart)
  • motion.stationaryTrackingMode / motion.stationaryPeriodicInterval / motion.stationaryPeriodicAccuracy: qué hacer una vez estacionario (arreglos periódicos frente a geocercas)

Aplicación → AppConfig

Before → Tracelet ───────────────────────────────────────────────────────────── stopOnTerminate → app.stopOnTerminate (default true) startOnBoot → app.startOnBoot (default false) heartbeatInterval → app.heartbeatInterval (default 60s) schedule → app.schedule (cron-like expressions)

Nota: scheduleUseAlarmManagerandroid.scheduleUseAlarmManager | preventSuspendios.preventSuspend

🔔 Notificación de servicio en primer plano → AndroidConfig.foregroundService

Importante (cambio 2.x.x): La notificación del servicio en primer plano ahora está configurada en android.foregroundService (un AndroidConfig), no en app. Este es un concepto exclusivo de Android.

Before (Notification) → Tracelet (AndroidConfig.foregroundService) ───────────────────────────────────────────────────────────── title → android.foregroundService.notificationTitle text → android.foregroundService.notificationText color → android.foregroundService.notificationColor smallIcon → android.foregroundService.notificationSmallIcon largeIcon → android.foregroundService.notificationLargeIcon priority → android.foregroundService.notificationPriority channelName → android.foregroundService.channelName channelId → android.foregroundService.channelId sticky → android.foregroundService.notificationOngoing actions → android.foregroundService.actions enabled → android.foregroundService.enabled

Sincronización HTTP → HttpConfig

Before → Tracelet ───────────────────────────────────────────────────────────── url → http.url (null = sync disabled) method → http.method (HttpMethod.post / .put) headers → http.headers httpRootProperty → http.httpRootProperty (default 'location') batchSync → http.batchSync maxBatchSize → http.maxBatchSize autoSync → http.autoSync autoSyncThreshold → http.autoSyncThreshold httpTimeout → http.httpTimeout (default 60000ms) params → http.params extras → http.extras locationsOrderDirection → http.locationsOrderDirection (LocationOrder enum)

🆕 Campos HttpConfig exclusivos de Tracelet:

  • http.disableAutoSyncOnCellular: sincronización solo por Wi-Fi: ¡guarda ese plan de datos!
  • http.maxRetries: valor predeterminado 10, con retroceso exponencial + fluctuación
  • http.retryBackoffBase: predeterminado 1000 ms
  • http.retryBackoffCap: predeterminado 300000 ms (5 min)

Geocercas → GeofenceConfig

Before → Tracelet ───────────────────────────────────────────────────────────── geofenceProximityRadius → geofence.geofenceProximityRadius (default 1000m) geofenceInitialTriggerEntry → geofence.geofenceInitialTriggerEntry (default true)
  • 🆕 geofence.geofenceModeKnockOut — Elimina automáticamente la geovalla después de la primera SALIDA: ¡una y listo!

Persistencia → PersistenceConfig

Before → Tracelet ───────────────────────────────────────────────────────────── persistMode → persistence.persistMode (.all / .location / .geofence / .none) maxDaysToPersist → persistence.maxDaysToPersist (-1 = forever) maxRecordsToPersist → persistence.maxRecordsToPersist (-1 = unlimited) locationTemplate → persistence.locationTemplate (Mustache-style) geofenceTemplate → persistence.geofenceTemplate (Mustache-style) disableProviderChangeRecord → persistence.disableProviderChangeRecord extras → persistence.extras

Registro → LoggerConfig

Before → Tracelet ───────────────────────────────────────────────────────────── logLevel (int const) → logger.logLevel (.verbose / .debug / .info / .warning / .error) logMaxDays → logger.logMaxDays (default 3) debug → logger.debug (alert sounds — fun at demos, terrifying at 3 AM)

🔐 Registro de auditoría → AuditConfig (exclusivo de Tracelet)

  • audit.enabledfalse de forma predeterminada. Cadena de hash SHA-256 en cada ubicación: manipulación = reventada
  • audit.hashAlgorithmHashAlgorithm.sha256
  • audit.includeExtrasInHashfalse por defecto

🛡️ Zonas de privacidad → PrivacyZoneConfig (exclusivo de Tracelet)

  • privacyZone.enabledfalse de forma predeterminada. Habilite el motor de zona de privacidad.

🎯 Constantes de precisión: ¡enumeraciones escritas!

Before (int constants) → Tracelet (typed enum) ───────────────────────────────────────────────────────────── Config.DESIRED_ACCURACY_NAVIGATION → DesiredAccuracy.high Config.DESIRED_ACCURACY_HIGH → DesiredAccuracy.high Config.DESIRED_ACCURACY_MEDIUM → DesiredAccuracy.medium Config.DESIRED_ACCURACY_LOW → DesiredAccuracy.low Config.DESIRED_ACCURACY_VERY_LOW → DesiredAccuracy.veryLow Config.DESIRED_ACCURACY_LOWEST → DesiredAccuracy.passive

📡 Eventos: mismos nombres, menos escritura

Las 14 transmisiones de eventos se mapean 1:1. Simplemente cambia el prefijo:

Before → Tracelet Callback Type ───────────────────────────────────────────────────────────────────────── onLocation(cb) → onLocation(cb) Location onMotionChange(cb) → onMotionChange(cb) Location onActivityChange(cb) → onActivityChange(cb) ActivityChangeEvent onProviderChange(cb) → onProviderChange(cb) ProviderChangeEvent onGeofence(cb) → onGeofence(cb) GeofenceEvent onGeofencesChange(cb) → onGeofencesChange(cb) GeofencesChangeEvent onHeartbeat(cb) → onHeartbeat(cb) HeartbeatEvent onHttp(cb) → onHttp(cb) HttpEvent onSchedule(cb) → onSchedule(cb) State onPowerSaveChange(cb) → onPowerSaveChange(cb) bool onConnectivityChange(cb) → onConnectivityChange(cb) ConnectivityChangeEvent onEnabledChange(cb) → onEnabledChange(cb) bool onNotificationAction(cb) → onNotificationAction(cb) String onAuthorization(cb) → onAuthorization(cb) AuthorizationEvent N/A → 🆕 onTrip(cb) TripEvent (auto-detected trips!) N/A → 🆕 onRemoteConfig(cb) Config (remote config applied) removeListeners() → removeListeners() Cancels all subscriptions
// Before — so many characters... bg.BackgroundGeolocation.onLocation((bg.Location location) { print('[location] $location'); }); // After — ahh, much better tl.Tracelet.onLocation((tl.Location location) { print('[location] $location'); });

🔧 Métodos: el mapeo completo

Ciclo vital

Before → Tracelet ───────────────────────────────────────────────────────────── bg.BackgroundGeolocation.ready(cfg) → tl.Tracelet.ready(cfg) bg.BackgroundGeolocation.start() → tl.Tracelet.start() bg.BackgroundGeolocation.stop() → tl.Tracelet.stop() bg.BackgroundGeolocation.startGeofences() → tl.Tracelet.startGeofences() N/A → 🆕 tl.Tracelet.startPeriodic() bg.BackgroundGeolocation.getState() → tl.Tracelet.getState() bg.BackgroundGeolocation.setConfig() → tl.Tracelet.setConfig() bg.BackgroundGeolocation.reset() → tl.Tracelet.reset() N/A → 🆕 tl.Tracelet.getHealth()

Ubicación

Before → Tracelet ───────────────────────────────────────────────────────────── getCurrentPosition(...) → getCurrentPosition(...) same params: desiredAccuracy, timeout, maximumAge, persist, samples, extras N/A → 🆕 getLastKnownLocation() — zero battery cost! watchPosition(cb, ...) → watchPosition(cb, ...) — returns watchId stopWatchPosition(id) → stopWatchPosition(id) changePace(isMoving) → changePace(isMoving) N/A → 🆕 updateLocationProviderOptions() — live accuracy/filter override, no pipeline restart getOdometer() → getOdometer() setOdometer(value) → setOdometer(value) resetOdometer() → setOdometer(0) — one less method to remember

Geocerca

Before → Tracelet ───────────────────────────────────────────────────────────── addGeofence(g) → addGeofence(g) addGeofences(list) → addGeofences(list) removeGeofence(id) → removeGeofence(id) removeGeofences() → removeGeofences() getGeofences() → getGeofences() N/A → 🆕 getGeofence(id) — get one without fetching all N/A → 🆕 geofenceExists(id) — quick existence check

Persistencia y sincronización

Before → Tracelet ───────────────────────────────────────────────────────────── getLocations() → getLocations([SQLQuery?]) — optional filtering! getCount() → getCount() destroyLocations() → destroyLocations() destroyLocation(uuid) → destroyLocation(uuid) insertLocation(params) → insertLocation(params) — returns UUID sync() → sync()

Permisos: tenemos ayudantes durante días

Before → Tracelet ───────────────────────────────────────────────────────────── requestPermission() → requestLocationAuthorization() N/A → 🆕 getLocationAuthorization() N/A → 🆕 hasBackgroundPermission (getter) N/A → 🆕 getNotificationAuthorization() N/A → 🆕 requestNotificationAuthorization() N/A → 🆕 getMotionAuthorization() N/A → 🆕 requestMotionAuthorization() N/A → 🆕 requestTemporaryFullAccuracyAuthorization(purpose) — iOS 14+ N/A → 🆕 canScheduleExactAlarms() — Android 12+ N/A → 🆕 openExactAlarmSettings() N/A → 🆕 openAppSettings() N/A → 🆕 openLocationSettings() N/A → 🆕 openBatterySettings() N/A → 🆕 isIgnoringBatteryOptimizations()

Explotación florestal

Before → Tracelet ───────────────────────────────────────────────────────────── getLog() → getLog([SQLQuery?]) — optional filtering destroyLog() → destroyLog() emailLog(email) → emailLog(email) log(level, msg) → log(level, msg)

Programación, tareas en segundo plano y sin cabeza

Before → Tracelet ───────────────────────────────────────────────────────────── startSchedule() → startSchedule() stopSchedule() → stopSchedule() startBackgroundTask() → startBackgroundTask() stopBackgroundTask(id) → stopBackgroundTask(id) registerHeadlessTask(cb) → registerHeadlessTask(cb)

Utilidad

Before → Tracelet ───────────────────────────────────────────────────────────── getProviderState() → getProviderState() getSensors() → getSensors() getDeviceInfo() → getDeviceInfo() playSound(name) → playSound(name) isPowerSaveMode → isPowerSaveMode N/A → 🆕 getSettingsHealth() — detects OEM battery killers N/A → 🆕 openOemSettings(label) — opens OEM settings page N/A → 🆕 requestSettings(action) N/A → 🆕 showSettings(action)

🔐 Seguimiento de auditoría (solo Tracelet: integridad de nivel empresarial)

  • verifyAuditTrail(): Verifique la cadena hash SHA-256. ¿Se manipuló algo?
  • getAuditProof(uuid) — Prueba criptográfica para un registro de ubicación específico

🛡️ Zonas de privacidad (solo Tracelet: el RGPD dice gracias)

  • addPrivacyZone(zone) — Agregar una zona con acción: excluir/degradar/solo evento
  • addPrivacyZones(list) — Agregado masivo
  • removePrivacyZone(id) — Eliminar por identificador
  • removePrivacyZones() — Eliminar todo
  • getPrivacyZones() — Listar todas las zonas

🎁 Funciones exclusivas de Tracelet

Funciones que obtienes con Tracelet que no están disponibles en flutter_background_geolocation:

  • Modo periódicoTracelet.startPeriodic() — Fijación de GPS cada N minutos a través de WorkManager. Sin servicio en primer plano, sin notificación, sin consumo de batería.
  • Filtro Kalmangeo.filter.useKalmanFilter: true — EKF de 4 estados suaviza el ruido del GPS. Tus pistas parecen profesionales, no borrachas.
  • Muestreo adaptativogeo.enableAdaptiveMode: true — Ajusta automáticamente el filtro de distancia según la actividad + batería + velocidad.
  • Detección simulada (3 niveles)geo.filter.mockDetectionLevel: detecta la suplantación de GPS mediante el recuento de satélites, la deriva en tiempo real y el análisis de marcas de tiempo.
  • Zonas de privacidadaddPrivacyZone() — Excluye, degrada o limita el seguimiento en áreas sensibles. Cumplimiento del RGPD integrado.
  • Pista de auditoríaverifyAuditTrail() — Cadena hash SHA-256. Demuestre que sus datos de ubicación no han sido manipulados.
  • Comprobación de estadogetHealth() — Una llamada te dice todo: permisos, GPS, batería, problemas OEM, 12 advertencias automáticas.
  • Compatibilidad OEMgetSettingsHealth() — Detecta asesinos de batería agresivos en Huawei, Xiaomi, Samsung, OPPO e indica a los usuarios cómo solucionarlos.
  • Detección de viajeonTrip(cb): detecta automáticamente viajes con distancia, duración, puntos de ruta y velocidad promedio.
  • Geocercas poligonalesGeofence(vertices: [...]) — No solo círculos. Dibuja cualquier forma con soporte poligonal de proyección de rayos.
  • Eliminación de geocercageofence.geofenceModeKnockOut — La geocerca se elimina automáticamente después de la primera SALIDA. Perfecto para alertas únicas.
  • Búsqueda de geocercasgetGeofence(id): consulta una única geocerca sin cargarlas todas.
  • Ayudantes de permisos: openAppSettings(), openBatterySettings(): enlaces profundos directos a la configuración del sistema.
  • Reintentos inteligenteshttp.maxRetries + retroceso — Retroceso exponencial con fluctuación. Tu servidor te lo agradecerá.
  • Sincronización solo por Wi-Fihttp.disableAutoSyncOnCellular: guarda datos móviles, sincroniza solo por Wi-Fi.
  • Movimiento solo del acelerómetromotion.shakeThreshold: detecta movimiento sin permiso de reconocimiento de actividad. Ventana emergente de permiso cero.
  • Soporte web: la misma API de Dart se ejecuta en el navegador para el seguimiento en primer plano (en pestañas). El seguimiento en segundo plano y varias funciones nativas no están disponibles; consulte Soporte web.

🤷 Funciones que aún no están en Tracelet

Algunas funciones del complemento anterior aún no están disponibles. Están planificados o se solucionan fácilmente:

  • Sincronización de geovalla del lado del servidorPlanificada. Por ahora, obtenga desde su API y llame a addGeofences().
  • Interpolación locationTemplateDeclarado, no cableado. Transforme en devolución de llamada onLocation o use http.extras.
  • Actualización automática de JWTDeclarado, no cableado. Configure http.headers manualmente; escuche onAuthorization.
  • Servidor de demostración: No planificado. Utilice su propio backend: cualquier punto final REST funciona.
  • Activación de clave de licencia — 🎉 ¡No es necesario! Es de código abierto.

🛠️ Migración paso a paso

Paso 1: actualice pubspec.yaml

dependencies: tracelet: ^3.6.14

Elimine flutter_background_geolocation y cualquier paquete de claves de licencia. ¡Ya no los necesitarás!

Paso 2: configuración de Android

Consulte INSTALL-ANDROID.md . Diferencias clave:

  • Dependencias opcionales: 🆕 Tracelet 2.0.0+ requiere que agregues explícitamente play-services-location a tu build.gradle si deseas un seguimiento GMS de alta precisión. De lo contrario, recurre al GPS AOSP estándar.
  • Sin clave de licencia: elimina cualquier configuración de BackgroundGeolocation.org de AndroidManifest.xml
  • Permisos: fusionados automáticamente a través de Gradle, no los declaras
  • minSdkVersion — API 21+ (igual que antes)
  • Kotlin: todo el código nativo es Kotlin

Paso 3: configuración de iOS

Consulte INSTALL-IOS.md . Diferencias clave:

  • Sin clave de licencia: elimine las entradas plist del complemento anterior
  • Modos en segundo plano: lo mismo: actualizaciones de ubicación, búsqueda en segundo plano, notificaciones remotas
  • Info.plist — mismas claves de descripción de uso (NSLocationAlwaysAndWhenInUseUsageDescription, etc.)
  • Podfile — elimina las fuentes de pods del complemento anterior

Paso 4: actualizar la configuración

Transforma tu piso Config() → compuesto Config(). Consulte la sección Configuración: de plano a estructurado más arriba.

Paso 5: actualizar los oyentes de eventos

Busque y reemplace bg.BackgroundGeolocation.onXxxtl.Tracelet.onXxx:

// Before bg.BackgroundGeolocation.onLocation((bg.Location location) { print('[location] $location'); }); // After tl.Tracelet.onLocation((tl.Location location) { print('[location] $location'); });

Paso 6: actualizar las llamadas del ciclo de vida

// Before bg.BackgroundGeolocation.ready(config).then((bg.State state) { if (!state.enabled) bg.BackgroundGeolocation.start(); }); // After tl.Tracelet.ready(config).then((tl.State state) { if (!state.enabled) tl.Tracelet.start(); });

Paso 7: actualice la tarea sin cabeza

// Before @pragma('vm:entry-point') void backgroundGeolocationHeadlessTask(bg.HeadlessEvent event) async { switch (event.name) { case bg.Event.LOCATION: bg.Location location = event.event; break; } } void main() { bg.BackgroundGeolocation.registerHeadlessTask(backgroundGeolocationHeadlessTask); runApp(MyApp()); } // After — shorter function name is a bonus 😎 @pragma('vm:entry-point') void headlessTask(tl.HeadlessEvent event) async { switch (event.name) { case 'location': tl.Location location = event.event as tl.Location; break; } } void main() { tl.Tracelet.registerHeadlessTask(headlessTask); runApp(MyApp()); }

📦 Carga útil HTTP: Snake_case → camelCase

¡Atención, desarrolladores backend! Una cosa es actualizar en su servidor.

flutter_background_geolocation envía esto:

{ "location": { "coords": { "latitude": 37.42, "longitude": -122.08, "accuracy": 12.3 }, "timestamp": "2026-03-06T10:30:00.000Z", "is_moving": true, "uuid": "abc-123", "odometer": 1234.5, "activity": { "type": "walking", "confidence": 85 }, "battery": { "level": 0.72, "is_charging": false }, "extras": { "custom_key": "custom_value" } } }

Tracelet envía esto:

{ "location": { "coords": { "latitude": 37.42, "longitude": -122.08, "accuracy": 12.3 }, "timestamp": "2026-03-06T10:30:00.000Z", "isMoving": true, "uuid": "abc-123", "odometer": 1234.5, "isMock": false, "activity": { "type": "walking", "confidence": 85 }, "battery": { "level": 0.72, "isCharging": false }, "extras": { "custom_key": "custom_value" } } }

TL;DR: is_movingisMoving, is_chargingisCharging, más un nuevo campo isMock. Actualice su análisis JSON y estará dorado.


🚨 Errores comunes

No los aprenda de la manera más difícil: nosotros ya lo hicimos:

  • Config ahora es compuesto: ajusta los campos en GeoConfig(...), AppConfig(...), HttpConfig(...), etc.
  • desiredAccuracy: -1 no funciona — Utilice DesiredAccuracy.high — enumeraciones escritas, no números mágicos
  • logLevel: 5 no funciona — Utilice LogLevel.verbose
  • No puedo encontrar resetOdometer() — Ahora es setOdometer(0)
  • La propiedad notification: desapareció — Es foregroundService: ForegroundServiceConfig(...) dentro de android: (AndroidConfig), no app
  • scheduleUseAlarmManager no está en AppConfig: ahora es android.scheduleUseAlarmManager
  • preventSuspend no está en AppConfig: ahora es ios.preventSuspend
  • El backend no puede analizar is_moving — Ahora es isMoving (camelCase)
  • ¿Aún tienes el código de clave de licencia? — Elimínalo — Tracelet no lo necesita
  • Las propiedades de State se ven diferentes: consulte la Referencia de API 
  • Errores de tipo HeadlessEvent.event — Emitirlo: event.event as tl.Location

📚 Más recursos


Bienvenido al lado de código abierto. Tenemos galletas. 🍪