Limitations
We would rather you know the gaps up front than discover them after integrating.
iOS only
There is no macOS, watchOS or Catalyst support, and none is planned — the engine is a mobile tracking engine. For Android, use the Android SDK or a cross-platform SDK.
The toolchain floor moves with each release
An engine release built by a newer Xcode raises the minimum Xcode for the whole package. This is inherent to shipping a binary framework, not a policy choice. See Compatibility.
The blue indicator is not optional on the default path
While tracking with Always authorization, the session engine keeps a
CLBackgroundActivitySession alive — and that session is what keeps
background delivery working. iOS shows the blue pill for its whole lifetime and
provides no API to hide it.
showsBackgroundLocationIndicator
only affects the legacy CLLocationManager path
(useSessionEngine: false),
which is materially less reliable in the background. When In Use shows the pill
regardless.
Android-only config keys
Accepted for API compatibility and ignored here: foregroundService,
notification.*, backgroundPermissionRationale,
stationaryLocationUpdateInterval, activityRecognitionInterval,
locationUpdateInterval, disableAutoSyncOnCellular’s cellular detection
nuances, and maxMonitoredGeofences above the platform budget. You can leave
them set — a config shared with an Android build stays valid.
Behaviour worth knowing before you ship
Geofence transitions fire past the boundary. Core Location reports ENTER
and EXIT only after the device has cleared the radius plus a system cushion: an
EXIT typically arrives tens of seconds after the geometric crossing — at
driving speed that is hundreds of metres — and in the worst case minutes later.
The location on the event is the last accepted fix when iOS delivered the
transition, not the point where the circle was crossed. A 50 m geofence in a
car is mostly a coin flip.
Twenty regions, and nine are ours. iOS caps monitored regions at 20 per app;
the engine spends one on its own wake region and, by default, eight more on the
wake ring, so 11 of your
geofences are armed at a time (19 with wakeRegionRingCount: 0). It keeps the nearest ones registered and swaps as you move — see
geofenceschange.
The first minutes of a session report isMoving: nil. Motion is probed
after start(), for up to stopTimeout. Treat nil as “not yet known”, never
as false.
The Simulator proves nothing about background behaviour. Location simulation, Core Motion and process relaunch all behave differently there.
App Review scrutinises background location. Expect to justify it: the purpose strings must describe a benefit the user gets while the app is closed, and a build that asks for Always without a visible feature that needs it is a common rejection.
Distracted-driving detection cannot see the driver
distractionDetection detects the phone being physically handled at driving
speed. It is not a “texting while driving” detector, and its limits should be
stated plainly:
- Neither platform can tell the driver from a passenger.
- Neither can see typing, message content, or which app is in use.
- Use of a mounted phone (tapping navigation, changing music on a cradled device) is largely invisible — the device barely moves.
- iOS cannot see screen state at all — its signal is strictly “the phone was physically handled at driving speed”.
- Android sees screen on/unlocked but not content — it cannot tell what the screen is showing, only that it’s on.
- Calls are not detected in this version — the
"c"cause value is reserved for a future release.
See Config.distractionDetection
and the distraction event.
Deliberately out of scope
A large part of the Transistorsoft API is not here and is not planned:
schedule/startSchedule, location and geofence templates, getLocations()
pagination and SQL queries, startBackgroundTask/stopBackgroundTask,
getDeviceInfo/getSensors, emailLog, reset(), startGeofences()
geofence-only mode, and persistMode/timestampFormat/
locationsOrderDirection. The Methods reference
is the complete list of what exists.