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',
        );
    }
  });
}