Flutter SDK - Initializing the SDK

Configuration options for the Flutter tracker's start method

Flutter SDK ⁠-⁠ Initializing the SDK

  • Flutter 3.41 or newer (Dart SDK ^3.0.0).
  • An OpenReplay backend of v1.26.0 or newer. Older backends report no frames support: events are still recorded, but the screen is not.

The package has no pub dependencies — the wire protocol, batching, gzip and multipart are all implemented in Dart, and everything native goes through a single platform channel.

flutter pub add openreplay

Or add it to your pubspec.yaml:

dependencies:
  openreplay: ^1.0.9

You must pass the projectKey to start(). You can get this value from your OpenReplay dashboard under ‘Preferences > Projects’.

Wrap your app in OpenReplayWidget, then start the tracker. The wrapper is required: it provides the repaint boundary frames are captured from, so without it nothing is recorded.

import 'package:flutter/material.dart';
import 'package:openreplay/openreplay.dart';

void main() {
  runApp(const OpenReplayWidget(child: MyApp()));
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      await OpenReplay.instance.start(
        projectKey: 'YOUR_PROJECT_KEY',
        // not required if you're using our SaaS version
        serverUrl: 'https://your.instance.com/ingest',
      );
    });
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
        // records screen transitions
        navigatorObservers: [ORNavigatorObserver()],
        home: const HomePage(),
      );
}

start() is safe to call before the first frame — capture only begins once OpenReplayWidget has laid out.

Setting up the navigation listener

Section titled Setting up the navigation listener

Add ORNavigatorObserver to your MaterialApp (or CupertinoApp, or any Navigator) so pushed and popped routes appear in the replay timeline:

MaterialApp(
  navigatorObservers: [ORNavigatorObserver()],
  // ...
)

Routes are reported by route.settings.name. Unnamed routes fall back to their position in the stack (route/2), so named routes give far more readable timelines.

See how to sanitize data in Flutter replays for more details.

Options are passed as OROptions to start():

await OpenReplay.instance.start(
  projectKey: 'YOUR_PROJECT_KEY',
  options: const OROptions(
    logs: false,
    targetLongEdge: 1080,
  ),
);
  • crashes: bool Captures Dart errors. Native crashes still need a native reporter. Default: true.
  • analytics: bool Captures touches, swipes, screens and inputs. Default: true.
  • performances: bool Captures CPU, memory, battery and thermal state. Default: true.
  • logs: bool Captures debugPrint output. Default: true.
  • screen: bool Enables frame capture. Default: true.
  • screenshotBatchSize: ScreenshotBatchSize Frames buffered before a batch is packed and uploaded — low (10), normal (20) or high (30). Default: normal.
  • targetLongEdge: int Longest edge of a captured frame, in pixels. Caps per-frame cost so it does not swing with screen size. Default: 720.
  • dedupeFrames: bool Skips frames whose pixels are byte-identical to the previous one. Playback is unaffected — the player holds the last snapshot at or before the current time. Default: true.
  • maskPlatformViews: bool Covers platform views (WebView, maps, camera preview) with a placeholder. They render in native layers Flutter cannot read back, so without this they appear blank. Default: true.
  • wifiOnly: bool Reserved; not yet enforced. Default: true.
  • debugLogs: bool Enables the SDK’s own logging. Default: false.
  • debugImages: bool Dumps captured frames for debugging. Default: false.

Two presets are provided: OROptions.defaults (all of the above) and OROptions.defaultDebug (the same, with debugLogs: true).

serverUrl defaults to OpenReplay Cloud. Self-hosted deployments pass it to start(), or set it ahead of time:

OpenReplay.instance.serverUrl = 'https://your.instance.com/ingest';

If you have any questions about this process, feel free to reach out to us on our Slack or check out our Forum.