Skip to main content
The React Native, Flutter and Capacitor packages forward every call to the native iOS and Android SDKs. The three share method names, event names and payload keys, and no reading logic runs in JavaScript or Dart. The React Native module works on the legacy bridge and, through the interop layer, on the New Architecture. Minor releases may add events, enum cases and error codes: keep a default branch (Versioning).

Methods

Any call can also fail with internalError (a bug), and every call fails with UNAVAILABLE on the Capacitor web build (Errors).

One session at a time

There is no session object. start() creates the wrapper’s one session and starts it, and you call start() again to retry.
  • While the session runs, start() rejects with invalidUsage, so call stop() first.
  • A start() that rejects keeps no session, so call it again once the cause is fixed.
  • completed or failed ends the session, and the next start() begins a new one without stop(). A cancelled event does not end it: the next reading starts by itself (how retries work).
  • stop() releases the session. Stopped after measurementComplete, it still delivers the outcome, then ends (Finalizing). A start() before that outcome arrives supersedes the old session and drops its remaining events.
  • setAutoStartEnabled(false) before start() holds that session, and the setting goes back to true when the session ends (Holding the start).
  • activate, deviceSupport and camera permission are app-wide.

Events

Every key is always present, with null for an absent optional. TypeScript names the payloads GuidanceEvent, StartedEvent, PreviewEvent, HeartbeatEvent, CancelledEvent, MeasurementCompleteEvent, CompletedEvent and FailedEvent, with the VitalsEvent union and VitalsEventPayload<Name>. Dart uses the same names for the subclasses of the sealed VitalsEvent. What each event means: Events.

Types

Fields are final. Enum values are the same on iOS and Android.
  • VitalsResult is the Result JSON. TypeScript receives it as is in completed. In Dart, toMap() writes it, VitalsResult.fromMap reads it back, and results compare by value.
  • LivePreview: heartRateBpm is null until there is a heart rate, rmssdMs until about 20 seconds in, and signalLevel until the first scored preview. Each reading’s first preview follows started at once, with progress 0 and every other value null.

Errors

A rejection (TypeScript) or a thrown VitalsException (Dart) carries code and message. Match on code, the message is informational. Methods lists what each call rejects with. The failed event’s error has the same shape, with cameraUnavailable (the camera could not be opened, or stopped and could not be restored) or internalError, and the session has ended. Dart maps a code the package does not know to unknown, and delivers errors on NeurofitVitals.events as VitalsException too. invalidUsage means a calling mistake in your app: What to do about each code: Failures.

Reading flow (React Native and Flutter)

Both packages export the pre-built flow and its parts. Screens, options, theme and strings: Pre-built reading flow. The camera preview and the building blocks may change in minor releases (Building blocks).

Threads

Events arrive in native order. Call any method from your JavaScript or Dart code: the wrappers move to the main thread themselves.

Platform differences