Skip to content

Migrating from Transistorsoft

BGeo’s Dart API is intentionally shaped like Transistorsoft’s commercial background-geolocation SDK family — the same method names, event names, and config-key vocabulary Transistorsoft uses across its React Native, Cordova, and native bindings carries over to bgeo_background_geolocation almost unchanged, so most integrations move over with small changes. This page inventories what maps directly, what differs, and what BGeo deliberately does not implement. It’s factual, not a comparison or a claim of equivalence — BGeo is a compatible engine, not a clone.

Install swap

Only the dependency changes. Method names, the facade shape, and the location object stay the same.

  1. Remove your existing Transistorsoft plugin dependency from pubspec.yaml and add BGeo:

    Terminal window
    flutter pub remove <your_old_transistorsoft_dependency>
    flutter pub add bgeo_background_geolocation
  2. Update every import to the new package, using the hide State/as bg convention (the SDK’s own State snapshot type collides with Flutter’s State<T> widget-state class otherwise):

    import 'package:bgeo_background_geolocation/bgeo_background_geolocation.dart' as bg;
  3. Follow Installation for the Android Maven repo and iOS deployment target — these replace whatever native setup your previous plugin required. Check Compatibility first: BGeo requires Android minSdk 24, iOS 15.5+, and a reasonably current Flutter/Dart SDK (null-safety, Future/Stream-based API) — there is no Flutter web or desktop support, since the tracking engine is mobile-only.

Drop the license key

BGeo is free and needs no license key. Delete Transistorsoft’s license entry — the com.transistorsoft.locationmanager.license meta-data in AndroidManifest.xml and the TSLocationManagerLicense key in ios/Runner/Info.plist — and add nothing in its place.

Config and method compatibility

Most Transistor config keys and methods behave identically — see the Config reference and Methods reference for exact Dart types and defaults. What maps directly (unchanged names and shapes, adapted only to Dart’s Future/named-constructor idiom):

  • Lifecycle: ready, setConfig, start, stop, getState, changePace
  • Positioning: getCurrentPosition, watchPosition, stopWatchPosition
  • Events: onLocation, onMotionChange, onHeartbeat, onProviderChange, onHttp, onConnectivityChange, onGeofence, onGeofencesChange — each returns a StreamSubscription in this Dart binding rather than a plain unsubscribe function
  • Permissions: requestPermission, getProviderState, requestTemporaryFullAccuracy, isPowerSaveMode/onPowerSaveChange
  • Odometer: getOdometer, setOdometer, resetOdometer
  • Upload queue: sync, getLocations, destroyLocations, getCount, destroyLocation, insertLocation
  • Geofences: addGeofence, addGeofences, removeGeofence, removeGeofences, getGeofences, geofenceExists — see the Geofencing guide
  • Logging: logger.error/warn/info/debug/verbose, getLog, destroyLog, uploadLog — see the Logging & debugging guide
  • HTTP config: url, method, headers, params, extras, httpRootProperty, autoSync, autoSyncThreshold, disableAutoSyncOnCellular, batchSync, maxBatchSize, maxRecordsToPersist
  • Motion/filter config: distanceFilter, stopTimeout, stationaryRadius, heartbeatInterval, desiredAccuracy, locationFilterPolicy, kalmanProfile
  • authorization (JWT refresh, now a typed Authorization object) — see the HTTP guide’s authorization section
  • The notification sub-keys (title, text, channelId, channelName, smallIcon, color, priority), now a typed Notification object

The location object shape is unchanged (coords, timestamp, isMoving, activity, battery, odometer, uuid, extras) — see Data types. Field names are camelCase Dart getters over the same snake_case wire payload (is_moving on the wire, isMoving on Location), a bridge-level convenience the JS binding doesn’t need to make since JS already uses whichever casing the wire sends.

A handful of keys are accepted for API compatibility but currently do nothing. Don’t rely on foregroundService or backgroundPermissionRationale, and note that debug only plays sound cues — see Limitations — accepted-but-no-op config keys before you build around any of them.

API parity: what’s not here

BGeo deliberately does not implement the following part of Transistorsoft’s surface — an SDK-level scoping decision independent of which language binding sits on top, so it applies here exactly as it does on any other BGeo binding:

Transistor API / configAlternative in BGeo
schedule / startSchedule / scheduleUseAlarmManagerRun your own scheduler (a Dart Timer, or a native alarm) that calls start()/stop().
locationTemplate / geofenceTemplateShape the upload body with httpRootProperty/params/extras instead of a template string — see Shaping the body.
transistorAuthorizationTokenN/A (Transistorsoft-account specific) — use authorization for your own backend.
Custom notification layout / actions / stringsThe supported Notification fields (title/text/channelId/channelName/smallIcon/color/priority) cover a fixed layout, not custom actions or arbitrary strings.
emailLoguploadLog() to your own logUrl endpoint instead of emailing a log file.
useSignificantChangesOnlyNo equivalent mode — the engine manages its own wake sources; see Tracking lifecycle — wake sources.
stopOnStationary / stopAfterElapsedMinutesCall stop() yourself from onMotionChange/onHeartbeat.
persistModeN/A — all tracked locations persist by default; a one-shot getCurrentPosition() fix opts in via its persist option instead.
timestampFormatN/A — timestamps are always ISO-8601 UTC strings, see Location.timestamp.
locationsOrderDirectionN/A — the persisted queue is always oldest-first, see Data pipeline — persistence.
Burst averaging (rollingWindow/burstWindow/maxBurstDistance), an onLocationFilter-style callback, kalmanDebug/filterDebugUnbuilt — these are unknown keys, silently stored but ignored by the native config dict. The implemented filter surface is locationFilterPolicy, kalmanProfile, and odometerAccuracyThreshold — use those instead of per-fix burst averaging or a filter-decision callback.
reset()Call setConfig() with the values you want restored — see the Config reference for the documented default of each key.
startGeofences() (geofence-only tracking mode)start() already runs geofences alongside location tracking — there’s no separate mode.
getLocations() pagination / SQLQuerygetLocations() returns the full queue, oldest-first, as a List<Location>; filter or paginate it in Dart. Note a large offline queue means a large payload crossing the platform channel in one call — a generic method-channel cost, not specific to this method.
startBackgroundTask() / stopBackgroundTask()N/A.
getDeviceInfo() / getSensors()N/A.

Behavioral differences worth knowing

  • No legacy failure-callback quirk. Some Transistorsoft bindings carry a quirk where supplying a failure callback makes ready()/start()/etc. resolve instead of reject/throw on an error. This Dart API was built Future-first from the start and has no callback parameters at all — a failed ready()/start()/stop() call always completes its Future with an error (typically a PlatformException), full stop. There’s nothing to migrate here beyond removing any old failure-callback handling.
  • sync() semantics are unchanged. It resolves with a List<Location> snapshot of the queue taken before the drain starts, not what remains afterward. See sync().
  • Headless dispatch is Android-only. registerHeadlessTask() runs your task in a background Flutter engine for seven event types (heartbeat, motionchange, geofence, providerchange, powersavechange, http, connectivitychange — location is excluded). The event arrives as HeadlessEvent(name, params), with every payload field other than name nested under params. Your task must be a top-level function or static method — Dart’s callback-handle mechanism can’t resolve a closure in a fresh isolate. iOS has no headless equivalent — see Boot & killed-app behavior: iOS: no headless.
  • iOS relaunch model differs internally, same external guarantee. BGeo keeps tracking alive across kill/reboot with a session-based engine (CLLocationUpdate.liveUpdates/CLBackgroundActivitySession, on by default on iOS 17+) plus significant-location-change monitoring and a rolling wake region, rather than Transistorsoft’s own implementation — see Boot & killed-app behavior for the full model.

Steps

  1. Install bgeo_background_geolocation; remove your old Transistorsoft dependency. Set up the Android Maven repo + iOS deployment target.
  2. Point every import at package:bgeo_background_geolocation/bgeo_background_geolocation.dart.
  3. Delete the Transistorsoft license entries from AndroidManifest.xml and Info.plist — BGeo needs no key.
  4. Move JWT/token-refresh settings into an Authorization object.
  5. Remove any usage of the keys/methods listed under API parity, and check Limitations for accepted-but-no-op keys.
  6. Test on a real device — background, kill/relaunch, reboot — see Boot & killed-app behavior.