Skip to content
Back to archipelago.banuacoder.com

Debug Tools

How to set up the App Blackbox session recorder contract in Flutter ​

Free Reference for app_blackbox: every variable, option and package it generates. Command: archipelago generate app_blackbox

Generate App Blackbox, learn which packages ship per flavor, set platform permissions, strip the recorder from production builds, and capture events.

What you'll learn ​

  • Generating the App Blackbox session recorder with filesystem snapshots and optional screen recording
  • Understanding the packages and which ones ship per build flavor
  • Configuring platform permissions for Android and iOS
  • Using build_prepare to strip the recorder from production builds
  • Capturing custom events and retrieving session archives
  • Reading the app's startup in the viewer's Launch view

Prerequisites ​

  • An existing Archipelago monorepo (see Monorepo Scaffolding)
  • Enterprise subscription, App Blackbox is not available on Free or Pro tiers

App Blackbox vs App Debugger: App Blackbox records a debug/staging session (metrics, filesystem events, optional screen capture) so you can diagnose issues after they occur. The production flavor strips it. App Debugger is an in-app overlay for developers to inspect state live. The two serve different purposes. You can use them together.

Step 1: Generate App Blackbox ​

bash
archipelago generate app_blackbox_recorder

The brick has one variable, uiKitPackageName, which it reads from archipelago.yaml. It generates its hard dependencies when they are missing:

  • app_blackbox (the free API and noop packages)
  • app_debugger
  • shared_consent and shared_identifiers

If the launch tracker is installed, the brick also wires its launch trace into the host app. Screen recording and filesystem snapshots are chosen at runtime, per session, through BlackboxConfig:

dart
await recorder.start(
  config: const BlackboxConfig(
    enableScreenRecording: false,     // default
    enableFilesystemSnapshots: true,  // default
  ),
);

Step 2: Understand the Generated Structure ​

Two bricks together make six packages:

text
features/app_blackbox/
├── app_blackbox_api/          # SessionRecorderSDK interface and models (free brick)
├── app_blackbox_noop/         # Inert stub for production flavors (free brick)
├── app_blackbox/              # Orchestrator and debug panel tab (this brick)
├── app_blackbox_filesystem/   # Filesystem snapshot recorder (this brick)
├── app_blackbox_metrics/      # CPU, memory and frame metrics (this brick)
└── app_blackbox_recording/    # Screen recording (this brick)

app_blackbox_api defines the contract. Feature code imports only this package. The production flavor swaps app_blackbox for app_blackbox_noop, so no recorder code ships in production. Internal flavors (development, staging, alpha, beta) keep the recorder, also in release mode.

Step 3: Check build_prepare ​

The post-generation hook adds the app_blackbox to app_blackbox_noop mapping to build_prepare.yaml. It also lists the three capability packages under debug_only. You add nothing by hand.

Run before each build, with the build's own flavor. The generated Fastfile does this for you:

bash
# Internal flavors: the recorder stays
dart run monorepo_toolkit build-prepare --flavor beta

# Production flavor: app_blackbox_noop
dart run monorepo_toolkit build-prepare --flavor production

# Check that nothing leaked
dart run monorepo_toolkit build-prepare --check-leaks --flavor production

The command rewrites the app_blackbox dependency in the host app's pubspec.yaml. There is no runtime if/else. The noop package exports empty stubs with the same class names, so the injector needs no edit.

Step 4: Configure Platform Permissions ​

Android ​

Nothing to add. The recording plugin declares its own foreground-service and notification permissions and its mediaProjection service, and asks for capture permission at each start. The metrics plugin declares its own ACCESS_NETWORK_STATE permission. Production-flavor builds have neither plugin.

iOS ​

Add to ios/Runner/Info.plist:

xml
<key>NSPhotoLibraryUsageDescription</key>
<string>App Blackbox saves session archives to your photo library.</string>

Enable the ReplayKit capability in Xcode under Signing & Capabilities for the Runner target. You need it only if you start sessions with BlackboxConfig(enableScreenRecording: true).

Step 5: Check the Wiring ​

You write no registration code. The packages declare their modules under archipelago: di_modules, and the host injector imports only package:app_blackbox/app_blackbox.dart.

The hook adds GetIt.I<SessionRecorderSDK>(); at the archipelago:debug_panel_pages marker in app_debugger's lib/src/di/debug_tools.dart. This resolves the recorder at startup, so the Blackbox tab appears in the debug panel. SessionRecorderSDKImpl stays an eager SDK for this reason.

The app test harness picks up the recorder's test prerequisite. Run dart run monorepo_toolkit generate test-harness, then flutter test test/di/injector_test.dart.

Step 6: Record a Session ​

Recording needs the user's diagnostics consent. Turn on Diagnostics consent in the Blackbox tab of the debug panel, or record the decision from your own consent screen with getIt<ConsentGate>().record(purpose: ConsentPurpose.diagnostics, granted: true). Until then start() throws StateError.

dart
final recorder = getIt<SessionRecorderSDK>();

// Start a session — returns a unique session ID
final sessionId = await recorder.start();

// Capture a custom event at any point
recorder.captureCustomEvent(
  'checkout_initiated',
  properties: {'amount': 99.99, 'currency': 'IDR'},
);

// Stop the session and retrieve the archive
final archive = await recorder.stop();

archive is a BundleArchive. It holds the .bbx ZIP bytes and a suggested file name. The ZIP has the event log, metrics samples, filesystem snapshots and, if enabled, the screen recording. stop() returns null when nothing was recorded or diagnostics consent was withdrawn.

Every stop also saves the bundle on the device. This holds for code, the Blackbox tab and the floating control. The Blackbox tab lists the saved sessions. Each row has Share, Copy path and Delete.

Step 7: View a Session Archive ​

Use Share on the session row to move the .bbx file to your computer, then open it in the Blackbox Viewer:

https://archipelago.banuacoder.com/blackbox

The viewer renders the event timeline, metrics graphs, and screen replay side by side. The browser processes archives locally. No data goes to Archipelago servers.

Open the Launch view to see how the app started. The recorder adds the launch trace to every bundle when the launch tracker is present. Every generated app has it. The waterfall shows which initializers delayed the first frame. It also shows which ran in parallel and which waited in a queue. The critical path is highlighted. Use it to find the step worth making faster. See The Launch view.

Key Configuration Points ​

CustomizationWhere to Change
Snapshot directoriesThe path list in the snapshot config of app_blackbox_filesystem
Metrics sample rateThe collection interval in app_blackbox_metrics
Auto-start on launchCall recorder.start() during post-launch init in bootstrap.dart
Upload archive to your backendAfter recorder.stop(), POST the archive file via the Network SDK

Next Steps ​