tracelet_ios 3.3.2 copy "tracelet_ios: ^3.3.2" to clipboard
tracelet_ios: ^3.3.2 copied to clipboard

PlatformiOS

iOS implementation of the Tracelet background geolocation plugin.

3.3.2 #

  • FIX (Location data, Android/iOS): Several location-map fields surfaced as static/default values in the Dart layer because the native-map → platform-channel converters dropped or mis-keyed them (#175):

    • getCurrentPosition(extras:, desiredAccuracy:) were silently ignored on Android (never forwarded to the SDK) — now applied.
    • battery.isCharging was always false — the converter read isCharging instead of the native snake_case is_charging.
    • isMoving was always false — read isMoving instead of native is_moving.

    Converters now read the native keys (with camelCase fallback), and field-by-field regression tests over the converters were added on both platforms to prevent recurrence.

  • TUNE (Crash detection): Lowered the default crashGThreshold from 3.0 g to 2.0 g. Validation against the large VZCrash field dataset showed the 3.0 g speed-gated rule missed ~48% of real crashes (median impact ~2.2 g) while the false-positive budget was small. Crash detection is opt-in with a cancel-countdown, so the default now favours recall — raise it if you see too many prompts. See #173. (Crash detection remains beta pending first-party field validation.)

3.3.1 #

  • CHORE: version bump for patch release

3.3.0 #

  • FEAT (Driving & Safety): On-device driving-behavior telematics — harsh_braking / harsh_acceleration / harsh_cornering / speeding via TelematicsConfig + Tracelet.onDrivingEvent (opt-in, default off) (#163).
  • FEAT (Driving & Safety): On-device transport-mode classifier (still/walking/running/cycling/vehicle) fusing accelerometer + GPS via ClassifierConfig + Tracelet.onModeChange (#164).
  • FEAT (Driving & Safety): Crash & fall detection with a cancel-countdown confirmation flow via ImpactConfig + Tracelet.onImpact and Tracelet.confirmImpact / Tracelet.cancelImpact (opt-in, default off) (#165).
  • All three features are default-off and side-channel — no change to existing tracking when disabled. See Driving & Safety.

3.2.19 #

CHORE: version bump for patch release

3.2.18 #

  • FIX (Native): ready() / getState() now populate State.config with the active configuration instead of leaving it permanently null (#147).
  • FEAT: Add HttpConfig.syncInterval for interval-based sync — the documented repeating-timer cadence was missing from the Dart config and the Pigeon layer; the native interval timer now flushes the offline queue on this cadence (#149).
  • FIX (Native): destroySyncedLocations() returns the real number of synced-and-pruned locations instead of a hardcoded 0 stub (#154).
  • FEAT: Expose the offline queue with getPendingLocations() and getPendingLocationCount() (#159).
  • FIX (Native): Honor the useKalmanFilter config key so the Extended Kalman Filter is no longer silently disabled by a key mismatch (#148).
  • FIX (Native): Propagate the detected activity (walking / driving / still) into recorded locations — fixes a permanent "activity": "unknown" (#155).
  • FIX (Native): Rebuild the native location processor when ready() applies a new config, so settings such as distanceFilter take effect immediately instead of using stale defaults (#157).
  • FIX (Native): getCount() honors time-bound queries instead of always returning the whole-database total (#152).
  • FIX: Guard the AuditConfig hash-algorithm mapping so configuring sha384 / sha512 no longer crashes with a fatal RangeError during ready() — unsupported variants fall back to sha256 (#150).
  • FIX (Native): The HTTP sync payload now includes each point's motion state is_moving (#151) and its trigger event (location / motionchange / heartbeat / geofence) (#156) — both were previously omitted by the native sync record.

3.2.17 #

  • FIX (Native): Resolve iOS auto-sync thread starvation by offloading synchronous HTTP requests to a background DispatchQueue to prevent blocking Swift Concurrency pools (#146).
  • CHORE (Docs): Fix Nextra changelog rendering bug and improve auto-translation glossary script for internationalization.

3.2.16 #

  • FIX (Native): Resolve Android/iOS getting stuck in the moving state and never transitioning back to stationary, which kept continuous GPS active and drained the battery. The accelerometer stillness sampler now stays active during the stop-timeout countdown and requires sustained motion — rather than a single noisy or stale sample — to abort it (#142).
  • FIX (Native): Background and post-reboot location captures are persisted (and therefore synced) again. Headless tracking (killed-state relaunch / boot) never calls ready(), so an internal readiness guard silently dropped every captured location before it reached the database, leaving auto-sync with nothing to upload.
  • FIX (Android): The foreground-service notification now reliably appears when the app is backgrounded or terminated with showNotificationOnPauseOnly enabled. The app's own foreground service skewed foreground/background detection (and OS process-importance updates lag), so the pause-only notification was suppressed even though tracking and syncing continued.

3.2.15 #

  • FIX (Native): Allow getState() and stop() to be called before ready() is invoked, correctly reporting persistent state and shutting down background services if the app was restarted from a killed state.
  • CHORE: Update dependencies and constraints.
  • FIX: Resolve MissingPluginException and test timing issues with setHasCustomSyncBodyBuilder.

3.2.14 #

  • FIX(sync): fix background auto-sync abortion when no custom builder is registered (Issue #134). (631542a1)
  • DOCS: add official documentation URL to all package READMEs. (9eb6951e)
  • DOCS: integrate nextra website and update pubspec URLs. (99b7fda8)

3.2.13 #

  • CHORE: Version bump to 3.2.13 to stay in lockstep with the federated set (Android startOnBoot reboot-tracking fix — see tracelet_android). No changes to this package.

3.2.12 #

  • CHORE: Re-release to align the full federated package set and native SDKs to a single consistent version. The 3.2.11 release published with mismatched versions across some packages (a few resolved to 3.2.10). No functional code changes.

3.2.11 #

  • FIX(ios): Fall back to the headless engine when a custom sync-body round-trip times out, instead of aborting the sync. Fixes location sync stopping after a few minutes while the app is backgrounded (Issue #134).

3.2.10 #

  • FIX: ensure geofence action (ENTER/EXIT/DWELL) is correctly parsed from nested payloads on all platforms and update CI to scan dynamic frameworks for symbols.

3.2.9 #

  • FIX(ios): Remove TraceletCore+Dummy.swift / TraceletSyncFFI+Dummy.swift@_silgen_name declarations from the old static library model caused "Undefined symbol" linker errors after the static→dynamic xcframework migration.
  • FIX(android): Catch ForegroundServiceStartNotAllowedException in LocationService.start() so calling ready() from the background on Android 12+ no longer crashes the host app; the foreground service start is deferred until the app returns to foreground.

3.2.8 #

  • FIX: Persist geofence ENTER/EXIT events in offline queue and auto-sync to server — events were previously dispatched to the app but never stored in the local SQLite database (Issue #128).
  • FIX: Structured event envelope (event_type, event_payload) for geofence events round-trips correctly through getLocations() and insertLocation().
  • FIX(sync): Stop POSTing malformed error payloads on failed HTTP sync requests; fix iOS custom-body deadlock in setSyncBodyBuilder (Issue #125).
  • FIX(android): Throw NOT_READY error before ready() is called to match iOS parity; previously Android silently ignored SDK calls before initialization (Issue #129).
  • FIX(ios): Resolve flutter_rust_bridge has not been initialized on release builds — TraceletCore is now a dynamic framework, preventing dead-code stripping of FRB symbols (Issues #116, #123, #124).
  • FIX(android): Resolve Failed to lookup symbol 'frb_get_rust_content_hash' — Rust symbols are now loaded directly from libtracelet_core.so bypassing RTLD_LOCAL isolation (Issues #116, #123).
  • PERF(ios): Reduce background motion sensor CPU/battery usage — accelerometer polling is now paused when stationary (Issue #130).
  • FIX: Persist historical is_moving state per location record so getLocations() returns accurate values instead of always returning the current live state (Issue #126).

3.2.7 #

  • FIX(ios): prevent dead code stripping of flutter_rust_bridge symbols in release builds.
  • FIX(android): implement OEM hardening mitigations and introduce showPowerManager to handle aggressive battery restrictions on specific OEM devices.

3.2.6 #

  • PERF: Optimize database timestamp queries for O(log N) fast filtering and resolve precision bugs (Issue #119).
  • FEAT: Implement sslPinningFingerprints natively across iOS and Android with Rust configs.
  • FIX: Include pinned fingerprints in SSL verification error logs and messages.
  • FIX: Rate limit Android MotionDetector logcat flooding during stillness (Issue #121).
  • FIX: Resolve race conditions in tests for Issue 118.
  • REFACTOR: Update integration test to use Config.fromMap for comprehensive Tracelet configuration testing.

3.2.5 #

  • FIX: Resolved iOS accelerometer sensitivity mismatch (stationary lock) by normalizing incoming m/s² thresholds to g-force expected by CMMotionManager.
  • FIX: Unify motion detection initial state and resume behavior across Android and iOS, preventing incorrect forced states on app launch and correctly resuming saved states.
  • FIX: Resolved flutter_rust_bridge dynamic library load failures on release builds for users without use_frameworks! by preserving global symbols during Xcode stripping.

3.2.4 #

  • FIX(ios): safely resolve dynamic symbols when use_frameworks! :linkage => :dynamic is used.

3.2.3 #

  • FIX: Force speed motion manager to evaluate initial speed on Android to prevent the state machine from being permanently stuck in MOVING when indoors (#115).
  • FIX: Resolve flutter_rust_bridge has not been initialized crash by ensuring the Rust core is instantiated and initialized before accessing methods (#116).
  • CHORE: Sync release versions across all packages.

3.2.2 #

  • CHORE: Sync release versions across all federated packages and update Swift Package Manager configuration.

3.2.1 #

  • CHORE: Align federated package versions and include additional patch updates.

3.2.0 #

  • FEAT(ios): Add reverse geocoding functionality.

3.1.14 #

  • FIX(ios): prevent dead code stripping of flutter_rust_bridge symbols in SPM apps by referencing them explicitly in TraceletIosPlugin

3.1.10 #

  • FIX(ios): prevent dead code stripping of flutter_rust_bridge symbols in iOS release builds by setting DEAD_CODE_STRIPPING=NO in CocoaPods xcconfig.

3.1.9 #

  • FIX(android): conditionally apply kotlin-android plugin to support older flutter SDKs while preventing warnings in modern Flutter environments.
  • CHORE(ci): add strict pre-publish flutter build verification step to release.yml.

3.1.8 #

  • Fix iOS SPM publishing

3.1.7 #

  • FIX(android): apply kotlin-android plugin to fix gradle build errors on newer AGP versions.
  • FIX(ios): fix SPM source folder paths in release bundling to ensure SDK compiles properly via CocoaPods.
  • FIX(ios): fix duplicate module import errors by adding conditional import checks for TraceletSDK.

3.1.4 #

  • CHORE: Sync release versions across workspace.

3.0.1 #

  • FIX(ios): Add missing FlutterFramework dependency to SPM plugin configuration to resolve compilation failures and PlatformExceptions.

3.0.0 #

  • FEAT: Massive Architecture Rewrite — Core algorithms are now powered by a high-performance Rust Core using flutter_rust_bridge.
  • FEAT: Smart Motion Mode — Introduced MotionDetectionMode.smart powered by the Rust battery budget engine.
  • FEAT: Migrated all platform event channels to use strongly-typed Pigeon bridges.

2.1.0 #

  • FIX: resolve background tracking loops, location stream drops, and permission issues. (8abc7d41)
  • FIX: refactor string comparisons to enum indexing across all layers. (b591b246)
  • FIX: refactor speed motion strings to typed enums across Flutter, Pigeon, Android, and iOS SDKs. (e974b728)
  • FEAT(android): smart foreground notification visibility. (fbf46b27)
  • FEAT: Speed-Based Motion Detection (#83). (5421e7a0)

2.0.8 #

  • FIX(ios): Resolved type casting bug for 64-bit Pigeon Int64 integer values across all iOS config mappings. This ensures that integer configurations (such as stopTimeout) sent from Dart are correctly applied on iOS.
  • PERF(ios): Avoid overriding GPS distanceFilter to continuous tracking during stopTimeout when preventSuspend is active, significantly reducing stationary battery drain.
  • CHORE: Bump native TraceletSDK dependency to 2.0.8.

2.0.7 #

2.0.6 #

  • CHORE: Update tracelet_platform_interface constraint to ^2.0.6.
  • CHORE: Bump native TraceletSDK dependency to 2.0.6.

2.0.5 #

  • CHORE: Version bump for monorepo consistency and package lockstep alignment.
  • CHORE: Update tracelet_platform_interface constraint to ^2.0.5.
  • CHORE: Bump native podspec version to 2.0.5.

2.0.4 #

  • CHORE: Version bump for monorepo consistency and native SDK alignment.
  • CHORE: Update tracelet_platform_interface constraint to ^2.0.4.

2.0.3 #

  • FIX: Removed unreliable timestamp drift heuristic from location spoofing detection.

2.0.1 #

  • FIX: Fixed persistent blue location indicator by properly conditionally disabling CLBackgroundActivitySession and startUpdatingLocation() in low-accuracy geofence-only mode.
  • CHORE: Bump native TraceletSDK dependency to 2.0.1.

2.0.0 #

  • BREAKING: Migrated to Pigeon for all platform-to-native communication, providing a type-safe interface for host and flutter API calls.
  • FIX: Resolved silent failures of native permission dialogs by ensuring all CoreLocation and CoreMotion requests are dispatched on the main thread.
  • FIX: Corrected CLAuthorizationStatus mapping in the native bridge to ensure accurate permission status reporting to Flutter.
  • CHORE: Bump native TraceletSDK dependency to 2.0.0.

1.9.3 #

2: 3: - CHORE: Bump native TraceletSDK dependency to 1.1.4. 4: 5: ## 1.9.2

  • CHORE: Constraint bump to tracelet_platform_interface 1.9.2. No iOS-side changes.

1.9.1 #

  • CHORE: Constraint bump to tracelet_platform_interface 1.9.1. No iOS-side changes.

1.9.0 #

  • FIX: Picks up the tracelet_platform_interface 1.9.0 fix that restores extras and vertices propagation for addGeofence (#58). No native-side changes.

1.8.13 #

  • PERF: Reduce first-fix latency on stationary → moving transitions. LocationEngine.changePace(true) now fires an additional one-shot requestLocation() so a fresh GPS fix arrives as soon as the hardware is warm, instead of waiting for distanceFilter on the continuous stream (#54).
  • FIX: Bump iOS native SDK to 1.0.11.

1.8.12 #

  • CHORE: Version bump for geofence/location extras round-trip fix in tracelet_android (#51 follow-up). iOS already handled extras correctly; regression tests added to lock in parity.

1.8.11 #

  • FIX: Guard against secondary FlutterEngine (e.g. Firebase background messaging) overwriting SDK singleton's event sender and callbacks (#51).

1.8.10 #

  • FIX: Version bump for killed-state tracking fix in tracelet_android (#50).
  • FIX: Bump iOS SDK to 1.0.10.

1.8.9 #

  • FEAT: Add syncInterval support — timer-based HTTP sync via DispatchSourceTimer (#50).
  • FEAT: Bump native SDK dependency to exact version 1.0.9.

1.8.8 #

  • FIX: Fix SubsystemTests static property access for HttpSyncManager callbacks.
  • FIX: Bump native SDK dependency to exact version 1.0.8.

1.8.7 #

  • CHORE: Align federated package versions and include additional patch updates.
  • FIX: Bump native SDK dependency to exact version 1.0.7.

1.8.6 #

  • FIX: getCurrentPosition(samples: 1) now uses startUpdatingLocation instead of CLLocationManager.requestLocation() — forces a fresh GPS fix with proper timeout instead of returning stale cached locations (#46).
  • PERF: Remove per-batch onRequestFreshHeaders invocation — eliminates latency before every sync request. Token refresh handled by onAuthorizationRequired on 401.
  • FIX: Bump native SDK dependency to exact version 1.0.6.
  • FIX: Privacy zones, audit trail, and encryption APIs now work before ready() — guards relaxed from isReady to manager != nil.

1.8.5 #

  • FIX: getCurrentPosition() falls back to last known location when CLLocationManager returns no fix (e.g. simulator, GPS-off) — fixes LOCATION_UNAVAILABLE errors (#46).
  • FIX: Bump native SDK dependency to exact version 1.0.5.

1.8.4 #

  • FIX: Pin native SDK dependency to exact version 1.0.4 — prevents CocoaPods from auto-resolving to incompatible newer releases.

1.8.3 #

  • FIX: Add isReady guards to getState(), setConfig(), reset(), getCurrentPosition(), changePace(), startSchedule(), stopSchedule() in Flutter bridge — returns safe defaults or NOT_READY error instead of crashing (re-fixes #46).

1.8.2 #

  • FIX: TraceletSdk.stop() now checks isReady before accessing managers — prevents crash when stop() is called before ready().
  • FIX: TraceletHostApiImpl.stop() returns NOT_READY PigeonError when called before initialization.

1.8.1 #

  • FIX: Periodic mode no longer shows persistent location indicator — removed CLBackgroundActivitySession from periodic tracking (it caused the blue arrow to stay on permanently instead of briefly during each fix).
  • TEST: Add BackgroundActivitySessionManager, ServiceSessionManager, and PeriodicModeBackgroundSession unit tests.

1.8.0 #

  • FIX: ConfigManager null-merge — filter NSNull values during merge so partial setConfig() does not overwrite existing non-null config.
  • FIX: Add missing import UIKit in LocationEngine.swift for UIBackgroundTaskIdentifier.
  • FIX: Align location map format — snake_case accuracy keys → camelCase (altitudeAccuracy, speedAccuracy, headingAccuracy), dead reckoning isChargingis_charging.
  • FIX: DB insertLocation reads camelCase accuracy keys with snake_case fallback; locationRowToMap outputs camelCase.
  • FEAT: Add destroySyncedLocations() — deletes only synced locations from the database.
  • FEAT: Auto-purge synced locations after successful HTTP sync in HttpSyncManager.
  • TEST: Add 28 location map format tests, 4 unit tests for ConfigManager null-merge and deleteSyncedLocations.

1.7.1 #

  • FIX: ConfigManager null-merge — filter NSNull values during merge so partial setConfig() does not overwrite existing non-null config.
  • FIX: Add missing import UIKit in LocationEngine.swift for UIBackgroundTaskIdentifier.
  • FEAT: Add destroySyncedLocations() — deletes only synced locations from the database.
  • FEAT: Auto-purge synced locations after successful HTTP sync in HttpSyncManager.
  • TEST: Add 4 unit tests for ConfigManager null-merge protection and deleteSyncedLocations.

1.7.0 #

  • FIX: Wire headlessFallback in eventSenderFactory (preventive — ensures future factory consumers can route to HeadlessRunner).
  • FIX: Move podspec to repo root for CocoaPods trunk push compatibility.
  • FEAT: Rewrite EventDispatcher to use Pigeon TraceletEventApi FlutterApi.
  • FEAT: Add TraceletHostApiImpl for type-safe Pigeon HostApi dispatch.
  • REFACTOR: Extract native SDK to standalone sdk/ios/ module (CocoaPods: TraceletSDK, SPM package).
  • REFACTOR: Wire Flutter plugin to published TraceletSDK pod.

1.6.3-alpha.1 #

  • FEAT: Rewrite EventDispatcher to use Pigeon TraceletEventApi FlutterApi instead of FlutterEventChannels.
  • FEAT: Add TraceletHostApiImpl for type-safe Pigeon HostApi dispatch.
  • REFACTOR: Extract native SDK code to sdk/ios/ module.
  • CHORE: Update cross-package dependency constraints to ^1.6.3-alpha.1.

1.6.1 #

  • FEAT: Add 401-aware retry — on HTTP 401 Unauthorized, invoke headless headers callback to refresh token, then retry once with updated dynamic headers.

1.6.0 #

  • FEAT: Add SSL certificate pinning — URLSessionDelegate-based validation with SHA-256 fingerprint matching via CommonCrypto.
  • FEAT: Add dynamic HTTP headers with runtime callback support and headless background execution.
  • FEAT: Add route context — attach arbitrary metadata to synced locations.
  • FEAT: Add custom sync body builder with headless callback support.
  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.6.0.

1.5.0 #

  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.5.0.

1.4.6 #

  • FIX: Rename PermissionManager to TraceletPermissionManager to avoid class name collision with permission_handler_apple (#32).
  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.4.6.

1.4.5 #

  • FEAT: Auto-request temporary full accuracy (iOS 14+) when tracking starts with reduced accuracy authorization.
  • TEST: Add XCTest unit tests for buildLocationMap() locationSource classification and reducedAccuracy field.
  • DOCS: Update INSTALL-IOS.md with TraceletFullAccuracy purpose key documentation.
  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.4.5.

1.4.4 #

  • FEAT: iOS 14+ reduced accuracy detection — engine logs warnings when approximate location is active and tracks authorization transitions.
  • FEAT: Add reducedAccuracy flag to each location fix — true when iOS grants only approximate location (~5 km).
  • FEAT: Improved locationSource classification — under reduced accuracy, source is classified as cell since iOS returns coarse fixes.
  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.4.4.

1.4.3 #

  • FEAT: Add locationSource classification to every location fix (gps, wifi, cell, unknown) based on horizontalAccuracy heuristic.
  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.4.3.

1.4.2 #

  • FIX: activateDeadReckoning() now retries via timer instead of silently returning when lastLocation is nil.
  • FIX: Add debug logging to GPS-loss timer and dead reckoning activation flow.
  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.4.2.

1.4.1 #

  • FEAT: Dead reckoning — full IMU sensor fusion implementation (DeadReckoningEngine). Uses CMDeviceMotion (fused accelerometer + gyroscope + magnetometer) for heading and step detection. Vehicle mode with acceleration integration.
  • FEAT: Auto-activation on GPS loss after configurable delay, auto-deactivation on GPS recovery or max duration.
  • CHORE: Add dead reckoning config getters to ConfigManager.
  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.4.1.

1.4.0 #

  • FEAT: Encrypted SQLite — database encryption via iOS Data Protection API (NSFileProtectionComplete).
  • FEAT: Device attestation — App Attest (DCAppAttestService) integration with challenge generation, token caching, and periodic refresh (DeviceAttestor).
  • FEAT: Remote config — fetch remote configuration via HTTPS with ETag caching and config-change event streaming.
  • FEAT: Dead reckoning — getDeadReckoningState() stub for future accelerometer/gyroscope-based position estimation.
  • FEAT: Carbon estimator — getCarbonReport() returns CO₂ estimates from tracked locations using EU average emission factors.
  • CHORE: Add DeviceCheck framework dependency.
  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.4.0.

1.3.6 #

  • FIX: getLocations() now honors SQLQuery.start and SQLQuery.end timestamp filtering.
  • FIX: getCount() now accepts optional SQLQuery for time-bounded counting.
  • CHORE: Update cross-package dependency constraints to ^1.3.6.

1.3.5 #

  • FIX: Fix Unable to find module dependency: 'TraceletCore' Swift compiler error by consolidating SPM targets into a single module and removing invalid cross-module imports.
  • FIX: Add missing AVFoundation, AudioToolbox, and Network framework linker settings in Package.swift.

1.3.4 #

  • CHORE: Update tracelet_platform_interface dependency constraint to ^1.3.3.

1.3.3 #

  • FIX: Bundle TraceletCore Swift source files directly inside the plugin package instead of depending on an unpublished local CocoaPod. Fixes unresolved import TraceletCore when installed from pub.dev.

1.3.2 #

  • PERF: Replace Foundation UUID() with C-level uuid_generate_random/uuid_unparse_lower in LocationEngine and TraceletDatabase (I-M6).

1.3.1 #

  • FIX: getPersistenceExtras() now reads distinct persistenceExtras config key with backward-compatible fallback.
  • PERF: markSynced() uses chunked SQL statements (500 UUIDs/chunk) instead of unbounded placeholder lists.

1.3.0 #

  • FIX: getState() always returned enabled: false on iOS — StateManager.toMap() flat-merged the config dictionary into the state dictionary, causing config keys (enabled from audit section, isMoving from motion section) to overwrite runtime state values. Config is now correctly nested under a "config" key, matching the Android implementation and the Dart State.fromMap() contract (#26).

1.2.1 #

iOS↔Android Parity Fixes #

  • FEAT: Add ConfigManager.hasConfig() — returns true if a config has been persisted at least once (checks UserDefaults for stored config data). Matches existing Android ConfigManager.hasConfig().
  • FEAT: Add StateManager.lastPeriodicLatitude / lastPeriodicLongitude — persisted coordinates for odometer computation across periodic tracking restarts. Returns NaN when no fix has been recorded; setting NaN removes the persisted value. Matches Android StateManager.lastPeriodicLatitude/Longitude.
  • FEAT: Add StateManager.addOdometer(distance:) — incremental odometer accumulation method. Matches Android StateManager.addOdometer(distance).
  • FEAT: Add LocationEngine.stopAllWatchers() — clears all active watch-position subscriptions. Called automatically from destroy(). Matches Android LocationEngine.stopAllWatchers().
  • FEAT: Add TraceletEventSending.hasListener(eventName:) protocol method and EventDispatcher.hasListener(eventName:) implementation — checks if a Dart listener is attached for a given event channel. Accepts both full path (com.tracelet/events/location) and short name (location). Matches Android EventSender.hasListener().
  • REFACTOR: All TraceletCore members made public for cross-module access with use_frameworks! CocoaPods integration.

1.2.0 #

  • CHORE: Version bump for federation consistency with tracelet_platform_interface 1.2.0 (new NotificationPriority and HashAlgorithm enums).

1.1.0 #

New Features #

  • FEAT: Add native DeltaEncoder (Swift) for delta-compressed HTTP sync payloads — mirrors the Dart implementation exactly for platform consistency. Encodes only field deltas between consecutive locations using shortened keys (la, lo, t, s, h, a, al, b), achieving 60–80% bandwidth reduction. Uses Foundation's ISO8601DateFormatter with fractional seconds fallback for robust timestamp handling.
  • FEAT: ConfigManager now reads and applies the following new configuration fields from Dart: batteryBudgetPerHour (adaptive battery budget target), enableSparseUpdates, sparseDistanceThreshold, sparseMaxIdleSeconds (app-level deduplication), enableDeadReckoning, deadReckoningActivationDelay, deadReckoningMaxDuration (inertial navigation when GPS lost), enableDeltaCompression, deltaCoordinatePrecision (HTTP delta encoding), and disableAutoSyncOnCellular (WiFi-only sync).
  • FEAT: HttpSyncManager now supports disableAutoSyncOnCellular — skips auto-sync when device is on cellular network, syncing only on WiFi. Also conditionally applies DeltaEncoder.encode() to multi-location batches before HTTP upload when enableDeltaCompression is enabled, reducing upload size by 60–80%.

1.0.2 #

  • FIX: handleReset() unconditionally removed geofence registrations from CLLocationManager even when stopOnTerminate: false was configured with trackingMode=1 (geofence mode). Geofences now survive the reset call so CLLocationManager continues monitoring regions after app termination (#23).

1.0.1 #

  • FIX: HTTP auto-sync never triggered from automatic location tracking — onLocationInserted() was only called from the manual insertLocation handler, not from LocationEngine.persistLocationIfAllowed() (#21).
  • FIX: ConfigManager.getHttpMethod() cast Int as String, silently ignoring HttpMethod.put — now correctly maps 0 → POST, 1 → PUT.
  • FIX: ConfigManager.getHttpHeaders() strict [String: String] cast could drop headers when platform channel delivers [String: Any] — now coerces values to strings.
  • FIX: maxBatchSize default corrected from 100 to 250 to match Dart and Android defaults.

1.0.0 #

🎉 Stable Release #

  • FEAT: First stable release of tracelet_ios.
  • REFACTOR: Remove third-party company name references.
  • All native iOS APIs are finalized and production-ready.

0.12.0 #

Performance Audit — 22 iOS issues resolved #

  • PERF: Cache ISO8601DateFormatter as static instance (I-C1, I-C2).
  • PERF: Call UIDevice.isBatteryMonitoringEnabled once at plugin initialization (I-C3).
  • PERF: Add serial stateQueue for thread-safe sync flag access (I-C4).
  • PERF: Use BackgroundTaskHelper.shared.begin() with proper expiration handler (I-C5).
  • PERF: Reduce accelerometer to 10 Hz and deliver on background queue (I-H1).
  • PERF: Set timer tolerance to 10% for iOS energy coalescing (I-H2).
  • PERF: Use SQLite transactions for batch geofence inserts (I-H3).
  • PERF: Throttle DB pruning to every 100 inserts (I-H4, I-H6).
  • PERF: Move JSON serialization outside DB queue lock (I-H5).
  • PERF: Default pausesLocationUpdatesAutomatically to true (I-M1).
  • PERF: Make activityType configurable via getActivityType() mapping (I-M2).
  • PERF: Reuse URLSessiongetAllTasks cancel instead of invalidateAndCancel (I-M3).
  • PERF: Defer BGAppRefreshTask.setTaskCompleted until async location fix returns (I-M4).
  • PERF: Find monitored region by identifier instead of creating dummy CLCircularRegion (I-M5).
  • PERF: Add in-memory privacy zone cache with CRUD invalidation (I-M7).
  • PERF: Add in-memory geofence cache with CRUD invalidation (I-M8).
  • PERF: Lazy-init CMMotionActivityManager and CMPedometer for accelerometer-only mode (I-L1).
  • PERF: Remove duplicate haversine() from GeofenceManager, call module-level function (I-L3).
  • PERF: Remove dead @available(iOS 14) self-assign no-op (I-L4).
  • REFACTOR: Remove trivial isMoreRestrictive() wrapper, inline isActionMoreRestrictive() call (I-L5).
  • CHORE: Add CoreLocation import to ConfigManager.swift for CLActivityType.

0.11.5 #

  • FIX: Persist polygon geofence vertices to SQLite — add vertices TEXT column with PRAGMA table_info migration for existing installs, and JSON serialization/deserialization in insertGeofence()/geofenceRowToMap().
  • FIX: Use NSNumber bridging for JSONSerialization vertex deserialization (fixes silent cast failure with [[Double]]).
  • FIX: Handle heterogeneous vertex arrays — skip non-array entries instead of failing the entire cast.
  • TEST: Add XCTest tests for geofence vertices CRUD (11 tests covering round-trip, validation, edge cases).
  • TEST: Add DB migration integration tests — column addition, data preservation, idempotency, multi-geofence migration, fresh install.

0.11.4 #

  • FIX: Revert over-aggressive allowsBackgroundLocationUpdates and significant-location guards — When In Use permission now works correctly for foreground and background tracking. iOS enforces permission at the OS level; only the killed-state entry point (autoResumeTracking) requires Always authorization.

0.11.3 #

  • FIX: Add .authorizedAlways guard to autoResumeTracking() — prevents "When In Use" permission from triggering tracking after app is relaunched from killed state via significant-location-change.
  • FIX: Guard allowsBackgroundLocationUpdates in configureLocationManager() and performPeriodicFix() — only set to true when Always authorization is granted.

0.11.2 #

  • CHORE: Tighten tracelet_platform_interface constraint to ^0.11.2.

0.11.1 #

  • FIX: Set event: "periodic" in all didUpdateLocations code paths for periodic tracking (was empty string).
  • FEAT: Add canScheduleExactAlarms (returns true) and openExactAlarmSettings (returns false) method channel stubs.
  • CHORE: Add NSLog diagnostic logging to startPeriodic() and performPeriodicFix().
  • CHORE: Bump platform interface to 0.11.1.

0.11.0 #

  • FEAT: AuditTrailManager — SHA-256 hash chain with SQLite persistence and UserDefaults chain state.
  • FEAT: PrivacyZoneManager — Haversine distance-based zone evaluation with exclude, degrade, and event-only actions.
  • FEAT: Privacy zones database table with CRUD operations.
  • FEAT: Audit trail database table with hash chain linkage.
  • FEAT: ConfigManager getters for audit and privacy zone configuration.
  • CHORE: Bump tracelet_platform_interface to ^0.11.0.

0.10.0 #

  • FEAT: Periodic mode — GPS-friendly interval tracking via startPeriodic(). Timer-based scheduling with background location toggling per fix.
  • FEAT: ConfigManager periodic config getters for interval, accuracy, foreground service, and exact alarms.
  • FIX: ConfigManager.swift escaped string literals causing Swift compilation failure.
  • CHORE: Bump tracelet_platform_interface to ^0.10.0.

0.9.1 #

  • FIX: Safe optional unwrap of UIBackgroundTaskIdentifier in HttpSyncManager.syncNextBatch() — fixes Swift compiler error.

0.9.0 #

  • FEAT: HTTP sync retry engine — configurable retry with exponential backoff for transient 5xx, 429, and timeout failures. Defers sync on connectivity loss via NWPathMonitor. Batch continuation loop.
  • FEAT: Configurable motion sensitivity — MotionDetector reads shakeThreshold, stillThreshold, stillSampleCount from ConfigManager at runtime (auto-converts m/s² to g-force).
  • CHORE: Bump tracelet_platform_interface to ^0.9.0.

0.8.3 #

  • FEAT: Proximity-based geofence auto-load/unload — only geofences within geofenceProximityRadius are registered with CLLocationManager, sorted by distance, capped at 20 (iOS limit). Enables monitoring thousands of geofences.
  • FEAT: GeofenceManager.updateProximity() — re-evaluates which geofences to monitor on every location update, dynamically swapping region registrations as the device moves.
  • FEAT: geofencesChange event fires with on/off arrays when geofences are activated/deactivated from proximity monitoring.
  • FEAT: maxMonitoredGeofences config respected — caps simultaneously monitored regions below the platform limit.
  • CHORE: Bump tracelet_platform_interface to ^0.8.3.

0.8.2 #

  • DOCS: Improve README visuals with combined Android & iOS demo image.

0.8.1 #

  • FEAT: BackgroundTaskHelper — central thread-safe utility wrapping UIApplication.beginBackgroundTask for safe background execution of native operations.
  • FEAT: iOS 17+ CLBackgroundActivitySession support via BackgroundActivitySessionManager — extends background runtime for location-tracking apps.
  • FEAT: iOS 18+ CLServiceSession support via ServiceSessionManager — maintains authorization state during background execution.
  • PERF: Wrap LocationEngine.didUpdateLocations in background task — protects persist + dispatch chain from iOS suspension.
  • PERF: Wrap HttpSyncManager.sync() in background task — protects entire HTTP upload + DB cleanup cycle.
  • PERF: Wrap HeadlessRunner.dispatchEvent() engine boot in background task — ensures Dart engine starts fully before iOS reclaims resources.
  • PERF: Wrap all TraceletIosPlugin lifecycle transitions (handleStop, handleReset, onStopRequested, handleScheduleStop, stopAfterElapsedTimer) in background tasks.
  • FIX: preventSuspendManager.start() now called in startGeofences() — was missing, causing audio keep-alive to not activate in geofence-only mode.
  • FIX: preventSuspendManager.stop() now called in all stop paths (reset, stopOnStationary, scheduleStop, stopAfterElapsed) — was only called in handleStop().
  • FIX: setConfig() now toggles preventSuspendManager mid-session when preventSuspend changes.
  • FIX: reset() now calls cancelStopAfterElapsedTimer() — was leaving stale timer running after reset.
  • FIX: iOS 17+/18+ session managers wired into all lifecycle paths (start, stop, startGeofences, reset, scheduleStart/Stop, stopOnStationary, stopAfterElapsed).

0.8.0 #

  • FEAT: OEM compatibility stubs — getSettingsHealth returns isAggressiveOem: false (iOS has no OEM power management issues), openOemSettings returns false.
  • DOCS: Update README with OEM compatibility note and documentation link.
  • CHORE: Bump tracelet_platform_interface to ^0.8.0.

0.7.1 #

  • DOCS: Add mock location detection feature to README with platform-specific detection details.
  • CHORE: Bump tracelet_platform_interface to ^0.7.1.

0.7.0 #

  • FEAT: Mock location detection — isLocationMock() uses CLLocationSourceInformation (iOS 15+) to detect simulated locations.
  • FEAT: Heuristic mock detection (level 2) — timestamp drift check (> 10s between location timestamp and system time = suspicious).
  • FEAT: buildLocationMap() includes mock flag and mockHeuristics metadata map (timestampDriftMs, platformFlagMock).
  • FEAT: Native-level mock rejection — when rejectMockLocations is enabled, drops mocked locations before sending to Dart and fires ProviderChangeEvent.mockLocationsDetected.
  • FEAT: ConfigManager.getMockDetectionLevel() and getRejectMockLocations() getters.
  • CHORE: Bump tracelet_platform_interface to ^0.7.0.

0.6.1 #

  • REFACTOR: Remove 6 dead ConfigManager methods for filtering migrated to Dart in 0.6.0 (getDisableElasticity, getElasticityMultiplier, getFilterPolicy, getMaxImpliedSpeed, getTrackingAccuracyThreshold, getUseKalmanFilter).
  • REFACTOR: Remove dead EventDispatcher.sendTrip() and "trip" channel registration — trip events now from Dart TripManager.
  • CHORE: Bump tracelet_platform_interface to ^0.6.1.

0.6.0 #

  • REFACTOR: Remove duplicate location filtering from LocationEngine.didUpdateLocations() — elasticity, distance filter, accuracy filter, and speed filter now handled by shared Dart LocationProcessor.
  • REFACTOR: Replace GeofenceManager.evaluateHighAccuracyProximity() with no-op stub — proximity evaluation moved to shared Dart GeofenceEvaluator.
  • CHORE: Bump tracelet_platform_interface to ^0.6.0.

0.5.5 #

  • FIX: onSchedule event now sends full state map (via stateManager.toMap()) instead of partial ["state": "on", "enabled": true] — fixes State.fromMap() crash on schedule events.

0.5.4 #

  • FIX: Heartbeat event now wraps location data in {"location": ...} to match HeartbeatEvent.fromMap() — fixes heartbeat always returning zero coordinates.
  • FIX: Heartbeat falls back to last known location (via buildLocationMap()) when getCurrentPosition returns null.

0.5.3 #

  • CHORE: Bump tracelet_platform_interface to ^0.5.3.

0.5.2 #

  • FEAT: Accelerometer-only motion detection mode — when disableMotionActivityUpdates is true, uses CMMotionManager raw accelerometer for permission-free stationary↔moving detection (no NSMotionUsageDescription required).
  • FEAT: getMotionAuthorizationStatus() / requestMotionPermission() return 3 (granted) immediately in accelerometer-only mode — no OS dialog shown.
  • PERF: Reuse shared CMMotionManager instance for sensor queries instead of creating throwaway instances.
  • FIX: Auto-fallback to accelerometer-only when CMMotionActivityManager.isActivityAvailable() returns false.

0.5.1 #

  • DOCS: Rewrite README with proper description, setup guide link, and related packages table.

0.5.0 #

  • CHORE: Bump tracelet_platform_interface to ^0.5.0.
  • CHORE: Bump version to 0.5.0.

0.4.0 #

  • FEAT: getMotionPermissionStatus() / requestMotionPermission() — CMMotionActivityManager authorization check.
  • FIX: Speed always zero in motionchange events — track lastEffectiveSpeed in LocationEngine.
  • FIX: "Upgrade to Always" dialog not appearing — fix handleStart isMoving initialization.
  • FIX: MotionDetector motion state bugs — proper accelerometer + activity recognition lifecycle.
  • CHORE: Bump tracelet_platform_interface to ^0.4.0.

0.3.0 #

  • FEAT: One-shot location via getCurrentPosition() with persist, samples, maximumAge, and extras parameters.
  • FEAT: Multi-sample collection with distanceFilter = kCLDistanceFilterNone and DispatchQueue timeout guard.
  • FEAT: getLastKnownLocation() — prefers own cached location, falls back to CLLocationManager.location.
  • FEAT: ForegroundServiceConfig.enabled support.
  • FIX: Add CLAuthorizationStatus guard in getCurrentPosition() — returns nil if not authorized instead of hanging.
  • FIX: Single-sample path now sets desiredAccuracy = kCLLocationAccuracyBest before requestLocation().
  • BREAKING: Requires tracelet_platform_interface: ^0.3.0.

0.2.4 #

  • Fix LICENSE file format for proper SPDX detection on pub.dev.

0.2.3 #

  • Fix ConfigManager.setConfig() — flatten nested section sub-maps (geo, app, http, etc.) sent by Dart before processing. Fixes all user config values being silently ignored in favor of defaults.

0.2.2 #

  • Fix duplicate keys in ConfigManager.defaultConfig() dictionary literal causing runtime crash.

0.2.1 #

  • Version bump for coordinated release.

0.2.0 #

  • Add Swift Package Manager support.
  • Fix podspec homepage URL.
  • Fix podspec source_files and resource_bundles paths for SPM layout.
  • Add SPDX license: Apache-2.0 identifier for pub.dev scoring.

0.1.0 #

  • Initial release.
  • CLLocationManager-based location tracking.
  • CoreMotion activity recognition.
  • SQLite3 persistence.
  • HTTP auto-sync with URLSession.
  • CLCircularRegion geofencing.
  • Headless FlutterEngine execution.
  • BGTaskScheduler integration.
  • Significant-change monitoring support.