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.
-
Remove your existing Transistorsoft plugin dependency from
pubspec.yamland add BGeo:Terminal window flutter pub remove <your_old_transistorsoft_dependency>flutter pub add bgeo_background_geolocation -
Update every import to the new package, using the
hide State/as bgconvention (the SDK’s ownStatesnapshot type collides with Flutter’sState<T>widget-state class otherwise):import 'package:bgeo_background_geolocation/bgeo_background_geolocation.dart' as bg; -
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 aStreamSubscriptionin 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 typedAuthorizationobject) — see the HTTP guide’s authorization section- The
notificationsub-keys (title,text,channelId,channelName,smallIcon,color,priority), now a typedNotificationobject
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 / config | Alternative in BGeo |
|---|---|
schedule / startSchedule / scheduleUseAlarmManager | Run your own scheduler (a Dart Timer, or a native alarm) that calls start()/stop(). |
locationTemplate / geofenceTemplate | Shape the upload body with httpRootProperty/params/extras instead of a template string — see Shaping the body. |
transistorAuthorizationToken | N/A (Transistorsoft-account specific) — use authorization for your own backend. |
Custom notification layout / actions / strings | The supported Notification fields (title/text/channelId/channelName/smallIcon/color/priority) cover a fixed layout, not custom actions or arbitrary strings. |
emailLog | uploadLog() to your own logUrl endpoint instead of emailing a log file. |
useSignificantChangesOnly | No equivalent mode — the engine manages its own wake sources; see Tracking lifecycle — wake sources. |
stopOnStationary / stopAfterElapsedMinutes | Call stop() yourself from onMotionChange/onHeartbeat. |
persistMode | N/A — all tracked locations persist by default; a one-shot getCurrentPosition() fix opts in via its persist option instead. |
timestampFormat | N/A — timestamps are always ISO-8601 UTC strings, see Location.timestamp. |
locationsOrderDirection | N/A — the persisted queue is always oldest-first, see Data pipeline — persistence. |
Burst averaging (rollingWindow/burstWindow/maxBurstDistance), an onLocationFilter-style callback, kalmanDebug/filterDebug | Unbuilt — 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 / SQLQuery | getLocations() 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
failurecallback makesready()/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 failedready()/start()/stop()call always completes itsFuturewith an error (typically aPlatformException), full stop. There’s nothing to migrate here beyond removing any old failure-callback handling. sync()semantics are unchanged. It resolves with aList<Location>snapshot of the queue taken before the drain starts, not what remains afterward. Seesync().- 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—locationis excluded). The event arrives asHeadlessEvent(name, params), with every payload field other thannamenested underparams. 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
- Install
bgeo_background_geolocation; remove your old Transistorsoft dependency. Set up the Android Maven repo + iOS deployment target. - Point every import at
package:bgeo_background_geolocation/bgeo_background_geolocation.dart. - Delete the Transistorsoft license entries from
AndroidManifest.xmlandInfo.plist— BGeo needs no key. - Move JWT/token-refresh settings into an
Authorizationobject. - Remove any usage of the keys/methods listed under API parity, and check Limitations for accepted-but-no-op keys.
- Test on a real device — background, kill/relaunch, reboot — see Boot & killed-app behavior.