initialize static method
void
initialize()
Registers the Dart masking handler so the native SDK can request
pre-masked frames. Call once at app startup (e.g. in main()).
Masking BEHAVIOUR — maskAllTexts / maskAllImages / textsToMask — is
configured on CXSessionReplayOptions and applied automatically by
CxFlutterPlugin.initializeSessionReplay. You do NOT set masking here;
CXSessionReplayOptions is the single source of truth.
Implementation
static void initialize() {
_installFrameTracker();
methodChannel.setMethodCallHandler((call) async {
switch (call.method) {
case 'getMaskRegions':
final ids = (call.arguments as List).cast<String>();
return _getMaskRegions(ids);
case 'captureMaskedFlutterView':
// Pace the captures. The native ~1fps timer fires
// regardless of whether the previous capture finished, and a capture
// (rasterise + tree walk + RGBA readback) competes with scroll
// rendering. Skip — reusing the last frame so the replay never goes
// black — when a capture is already running or the UI is actively
// animating. Only the scroll path advances the skip counter; the
// forced capture after _maxConsecutiveSkips keeps a long scroll from
// producing no frames at all.
if (_shouldSkip(_captureInFlight,
_sinceLastFrame.elapsedMilliseconds, _consecutiveSkips)) {
if (_captureInFlight == 0) _consecutiveSkips++;
return _lastCapture;
}
_consecutiveSkips = 0;
_captureInFlight++;
try {
final source = FlutterFrameSource.forImplicitView(
maskCollector: SessionReplayMasking.collectAllMaskRectsSync,
captureScale: _captureScale,
);
if (source == null) return _lastCapture;
final frame = await _captureFrameSynced(source);
final masked = await _compositeMasks(frame.image, frame.rects);
try {
final byteData =
await masked.toByteData(format: ui.ImageByteFormat.rawRgba);
if (byteData == null) return _lastCapture;
_lastCapture = {
'bytes': byteData.buffer.asUint8List(),
'width': masked.width,
'height': masked.height,
};
return _lastCapture;
} finally {
frame.image.dispose();
masked.dispose();
}
} catch (_) {
// Capture failed or timed out (e.g. the engine never committed a
// frame while backgrounded). Reuse the last good frame; the finally
// releases the in-flight guard so capture self-heals next tick.
return _lastCapture;
} finally {
_captureInFlight--;
}
default:
throw PlatformException(
code: 'unimplemented',
message: 'Method ${call.method} not implemented',
);
}
});
}